synapse 2.165.0__py311-none-any.whl → 2.167.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 +4 -10
- synapse/cmds/cortex.py +1 -6
- synapse/common.py +6 -0
- synapse/cortex.py +104 -57
- synapse/datamodel.py +32 -0
- synapse/exc.py +1 -0
- synapse/lib/agenda.py +81 -51
- synapse/lib/aha.py +2 -0
- synapse/lib/ast.py +21 -23
- synapse/lib/base.py +11 -10
- synapse/lib/cell.py +24 -24
- synapse/lib/hive.py +11 -0
- synapse/lib/httpapi.py +1 -0
- synapse/lib/nexus.py +3 -2
- synapse/lib/node.py +4 -2
- synapse/lib/schemas.py +3 -1
- synapse/lib/snap.py +50 -0
- synapse/lib/storm.py +19 -17
- synapse/lib/stormlib/aha.py +370 -17
- synapse/lib/stormlib/auth.py +11 -4
- synapse/lib/stormlib/cache.py +202 -0
- synapse/lib/stormlib/cortex.py +69 -7
- synapse/lib/stormlib/macro.py +11 -18
- synapse/lib/stormlib/spooled.py +109 -0
- synapse/lib/stormlib/stix.py +1 -1
- synapse/lib/stormtypes.py +61 -17
- synapse/lib/trigger.py +10 -12
- synapse/lib/types.py +3 -1
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +16 -3
- synapse/models/base.py +8 -0
- synapse/models/files.py +3 -0
- synapse/models/inet.py +74 -2
- synapse/models/orgs.py +52 -8
- synapse/models/person.py +30 -11
- synapse/models/risk.py +44 -3
- synapse/telepath.py +115 -32
- synapse/tests/files/stormpkg/dotstorm/dotstorm.yaml +3 -0
- synapse/tests/test_cortex.py +79 -8
- synapse/tests/test_datamodel.py +22 -0
- synapse/tests/test_lib_agenda.py +8 -1
- synapse/tests/test_lib_aha.py +19 -6
- synapse/tests/test_lib_cell.py +6 -2
- synapse/tests/test_lib_grammar.py +62 -64
- synapse/tests/test_lib_httpapi.py +1 -1
- synapse/tests/test_lib_rstorm.py +4 -4
- synapse/tests/test_lib_storm.py +98 -7
- synapse/tests/test_lib_stormlib_aha.py +196 -0
- synapse/tests/test_lib_stormlib_cache.py +272 -0
- synapse/tests/test_lib_stormlib_compression.py +12 -12
- synapse/tests/test_lib_stormlib_cortex.py +71 -0
- synapse/tests/test_lib_stormlib_macro.py +94 -0
- synapse/tests/test_lib_stormlib_spooled.py +190 -0
- synapse/tests/test_lib_stormtypes.py +71 -37
- synapse/tests/test_lib_view.py +50 -3
- synapse/tests/test_model_files.py +3 -0
- synapse/tests/test_model_inet.py +67 -0
- synapse/tests/test_model_risk.py +6 -0
- synapse/tests/test_telepath.py +30 -7
- synapse/tests/test_tools_genpkg.py +26 -0
- synapse/tests/test_tools_hiveload.py +1 -0
- synapse/tests/test_tools_hivesave.py +1 -0
- synapse/tests/test_tools_modrole.py +81 -0
- synapse/tests/test_tools_moduser.py +105 -0
- synapse/tests/utils.py +22 -3
- synapse/tools/autodoc.py +1 -1
- synapse/tools/hive/load.py +3 -0
- synapse/tools/hive/save.py +3 -0
- synapse/tools/modrole.py +59 -7
- synapse/tools/moduser.py +78 -10
- {synapse-2.165.0.dist-info → synapse-2.167.0.dist-info}/METADATA +3 -3
- {synapse-2.165.0.dist-info → synapse-2.167.0.dist-info}/RECORD +75 -72
- synapse/lib/provenance.py +0 -111
- synapse/tests/test_lib_provenance.py +0 -37
- {synapse-2.165.0.dist-info → synapse-2.167.0.dist-info}/LICENSE +0 -0
- {synapse-2.165.0.dist-info → synapse-2.167.0.dist-info}/WHEEL +0 -0
- {synapse-2.165.0.dist-info → synapse-2.167.0.dist-info}/top_level.txt +0 -0
synapse/axon.py
CHANGED
|
@@ -1509,7 +1509,6 @@ class Axon(s_cell.Cell):
|
|
|
1509
1509
|
atimeout = aiohttp.ClientTimeout(total=timeout)
|
|
1510
1510
|
|
|
1511
1511
|
async with aiohttp.ClientSession(connector=connector, timeout=atimeout) as sess:
|
|
1512
|
-
|
|
1513
1512
|
try:
|
|
1514
1513
|
data = aiohttp.FormData()
|
|
1515
1514
|
data._is_multipart = True
|
|
@@ -1523,7 +1522,9 @@ class Axon(s_cell.Cell):
|
|
|
1523
1522
|
|
|
1524
1523
|
sha256 = field.get('sha256')
|
|
1525
1524
|
if sha256:
|
|
1526
|
-
|
|
1525
|
+
sha256b = s_common.uhex(sha256)
|
|
1526
|
+
await self._reqHas(sha256b)
|
|
1527
|
+
valu = self.get(sha256b)
|
|
1527
1528
|
else:
|
|
1528
1529
|
valu = field.get('value')
|
|
1529
1530
|
if not isinstance(valu, (bytes, str)):
|
|
@@ -1547,9 +1548,6 @@ class Axon(s_cell.Cell):
|
|
|
1547
1548
|
}
|
|
1548
1549
|
return info
|
|
1549
1550
|
|
|
1550
|
-
except asyncio.CancelledError: # pramga: no cover
|
|
1551
|
-
raise
|
|
1552
|
-
|
|
1553
1551
|
except Exception as e:
|
|
1554
1552
|
logger.exception(f'Error POSTing files to [{s_urlhelp.sanitizeUrl(url)}]')
|
|
1555
1553
|
err = s_common.err(e)
|
|
@@ -1586,9 +1584,8 @@ class Axon(s_cell.Cell):
|
|
|
1586
1584
|
atimeout = aiohttp.ClientTimeout(total=timeout)
|
|
1587
1585
|
|
|
1588
1586
|
async with aiohttp.ClientSession(connector=connector, timeout=atimeout) as sess:
|
|
1589
|
-
|
|
1590
1587
|
try:
|
|
1591
|
-
|
|
1588
|
+
await self._reqHas(sha256)
|
|
1592
1589
|
async with sess.request(method, url, headers=headers, params=params,
|
|
1593
1590
|
data=self.get(sha256), ssl=ssl) as resp:
|
|
1594
1591
|
|
|
@@ -1601,9 +1598,6 @@ class Axon(s_cell.Cell):
|
|
|
1601
1598
|
}
|
|
1602
1599
|
return info
|
|
1603
1600
|
|
|
1604
|
-
except asyncio.CancelledError: # pramga: no cover
|
|
1605
|
-
raise
|
|
1606
|
-
|
|
1607
1601
|
except Exception as e:
|
|
1608
1602
|
logger.exception(f'Error streaming [{sha256}] to [{s_urlhelp.sanitizeUrl(url)}]')
|
|
1609
1603
|
err = s_common.err(e)
|
synapse/cmds/cortex.py
CHANGED
|
@@ -212,7 +212,7 @@ class StormCmd(s_cli.Cmd):
|
|
|
212
212
|
* nodeedits (default),
|
|
213
213
|
* count (just counts of nodeedits), or
|
|
214
214
|
* none (no such messages emitted).
|
|
215
|
-
--show-prov:
|
|
215
|
+
--show-prov: Deprecated. This no longer does anything.
|
|
216
216
|
--raw: Print the nodes in their raw format. This overrides --hide-tags and --hide-props.
|
|
217
217
|
--debug: Display cmd debug information along with nodes in raw format. This overrides other display arguments.
|
|
218
218
|
--path: Get path information about returned nodes.
|
|
@@ -256,7 +256,6 @@ class StormCmd(s_cli.Cmd):
|
|
|
256
256
|
'err': self._onErr,
|
|
257
257
|
'node:edits': self._onNodeEdits,
|
|
258
258
|
'node:edits:count': self._onNodeEditsCount,
|
|
259
|
-
'prov:new': self._onProvNew, # TODO remove in 3.0.0
|
|
260
259
|
}
|
|
261
260
|
self._indented = False
|
|
262
261
|
|
|
@@ -281,10 +280,6 @@ class StormCmd(s_cli.Cmd):
|
|
|
281
280
|
s_cli.Cmd.printf(self, '.' * count, addnl=False, color=NODEEDIT_COLOR)
|
|
282
281
|
self._indented = True
|
|
283
282
|
|
|
284
|
-
def _onProvNew(self, mesg, opts):
|
|
285
|
-
if opts.get('show-prov'):
|
|
286
|
-
self.printf(repr(mesg), color=PROVNEW_COLOR)
|
|
287
|
-
|
|
288
283
|
def _printNodeProp(self, name, valu):
|
|
289
284
|
self.printf(f' {name} = {valu}')
|
|
290
285
|
|
synapse/common.py
CHANGED
|
@@ -973,6 +973,12 @@ def unjsonsafe_nodeedits(nodeedits):
|
|
|
973
973
|
|
|
974
974
|
return retn
|
|
975
975
|
|
|
976
|
+
def reprauthrule(rule):
|
|
977
|
+
text = '.'.join(rule[1])
|
|
978
|
+
if not rule[0]:
|
|
979
|
+
text = '!' + text
|
|
980
|
+
return text
|
|
981
|
+
|
|
976
982
|
def reqJsonSafeStrict(item):
|
|
977
983
|
'''
|
|
978
984
|
Require the item to be safe to serialize to JSON without type coercion issues.
|
synapse/cortex.py
CHANGED
|
@@ -53,7 +53,6 @@ import synapse.lib.crypto.rsa as s_rsa
|
|
|
53
53
|
import synapse.lib.stormhttp as s_stormhttp # NOQA
|
|
54
54
|
import synapse.lib.stormwhois as s_stormwhois # NOQA
|
|
55
55
|
|
|
56
|
-
import synapse.lib.provenance as s_provenance
|
|
57
56
|
import synapse.lib.stormtypes as s_stormtypes
|
|
58
57
|
|
|
59
58
|
import synapse.lib.stormlib.aha as s_stormlib_aha # NOQA
|
|
@@ -74,6 +73,7 @@ import synapse.lib.stormlib.smtp as s_stormlib_smtp # NOQA
|
|
|
74
73
|
import synapse.lib.stormlib.stix as s_stormlib_stix # NOQA
|
|
75
74
|
import synapse.lib.stormlib.yaml as s_stormlib_yaml # NOQA
|
|
76
75
|
import synapse.lib.stormlib.basex as s_stormlib_basex # NOQA
|
|
76
|
+
import synapse.lib.stormlib.cache as s_stormlib_cache # NOQA
|
|
77
77
|
import synapse.lib.stormlib.graph as s_stormlib_graph # NOQA
|
|
78
78
|
import synapse.lib.stormlib.iters as s_stormlib_iters # NOQA
|
|
79
79
|
import synapse.lib.stormlib.macro as s_stormlib_macro
|
|
@@ -89,6 +89,7 @@ import synapse.lib.stormlib.random as s_stormlib_random # NOQA
|
|
|
89
89
|
import synapse.lib.stormlib.scrape as s_stormlib_scrape # NOQA
|
|
90
90
|
import synapse.lib.stormlib.infosec as s_stormlib_infosec # NOQA
|
|
91
91
|
import synapse.lib.stormlib.project as s_stormlib_project # NOQA
|
|
92
|
+
import synapse.lib.stormlib.spooled as s_stormlib_spooled # NOQA
|
|
92
93
|
import synapse.lib.stormlib.version as s_stormlib_version # NOQA
|
|
93
94
|
import synapse.lib.stormlib.easyperm as s_stormlib_easyperm # NOQA
|
|
94
95
|
import synapse.lib.stormlib.ethereum as s_stormlib_ethereum # NOQA
|
|
@@ -286,10 +287,8 @@ class CoreApi(s_cell.CellApi):
|
|
|
286
287
|
s_common.deprecated('CoreApi.addNode')
|
|
287
288
|
async with await self.cell.snap(user=self.user) as snap:
|
|
288
289
|
self.user.confirm(('node', 'add', form), gateiden=snap.wlyr.iden)
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
node = await snap.addNode(form, valu, props=props)
|
|
292
|
-
return node.pack()
|
|
290
|
+
node = await snap.addNode(form, valu, props=props)
|
|
291
|
+
return node.pack()
|
|
293
292
|
|
|
294
293
|
async def addNodes(self, nodes):
|
|
295
294
|
'''
|
|
@@ -317,16 +316,14 @@ class CoreApi(s_cell.CellApi):
|
|
|
317
316
|
done[formname] = True
|
|
318
317
|
|
|
319
318
|
async with await self.cell.snap(user=self.user) as snap:
|
|
320
|
-
with s_provenance.claim('coreapi', meth='node:add', user=snap.user.iden):
|
|
321
319
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
async for node in snap.addNodes(nodes):
|
|
320
|
+
snap.strict = False
|
|
321
|
+
async for node in snap.addNodes(nodes):
|
|
325
322
|
|
|
326
|
-
|
|
327
|
-
|
|
323
|
+
if node is not None:
|
|
324
|
+
node = node.pack()
|
|
328
325
|
|
|
329
|
-
|
|
326
|
+
yield node
|
|
330
327
|
|
|
331
328
|
async def getFeedFuncs(self):
|
|
332
329
|
'''
|
|
@@ -361,9 +358,8 @@ class CoreApi(s_cell.CellApi):
|
|
|
361
358
|
})
|
|
362
359
|
|
|
363
360
|
async with await self.cell.snap(user=self.user, view=view) as snap:
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
await snap.addFeedData(name, items)
|
|
361
|
+
snap.strict = False
|
|
362
|
+
await snap.addFeedData(name, items)
|
|
367
363
|
|
|
368
364
|
async def count(self, text, opts=None):
|
|
369
365
|
'''
|
|
@@ -1002,7 +998,16 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1002
998
|
'multiqueue': self.multiqueue,
|
|
1003
999
|
})
|
|
1004
1000
|
|
|
1005
|
-
|
|
1001
|
+
# TODO - Remove this in 3.0.0
|
|
1002
|
+
ag = await self.auth.addAuthGate('cortex', 'cortex')
|
|
1003
|
+
for (useriden, user) in ag.gateusers.items():
|
|
1004
|
+
mesg = f'User {useriden} ({user.name}) has a rule on the "cortex" authgate. This authgate is not used ' \
|
|
1005
|
+
f'for permission checks and will be removed in Synapse v3.0.0.'
|
|
1006
|
+
logger.warning(mesg, extra=await self.getLogExtra(user=useriden, username=user.name))
|
|
1007
|
+
for (roleiden, role) in ag.gateroles.items():
|
|
1008
|
+
mesg = f'Role {roleiden} ({role.name}) has a rule on the "cortex" authgate. This authgate is not used ' \
|
|
1009
|
+
f'for permission checks and will be removed in Synapse v3.0.0.'
|
|
1010
|
+
logger.warning(mesg, extra=await self.getLogExtra(role=roleiden, rolename=role.name))
|
|
1006
1011
|
|
|
1007
1012
|
self._initVaults()
|
|
1008
1013
|
|
|
@@ -1011,6 +1016,12 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1011
1016
|
(2, self._storLayrFeedDefaults),
|
|
1012
1017
|
), nexs=False)
|
|
1013
1018
|
|
|
1019
|
+
async def _viewNomergeToProtected(self):
|
|
1020
|
+
for view in self.views.values():
|
|
1021
|
+
nomerge = view.info.get('nomerge', False)
|
|
1022
|
+
await view.setViewInfo('protected', nomerge)
|
|
1023
|
+
await view.setViewInfo('nomerge', None)
|
|
1024
|
+
|
|
1014
1025
|
async def _storUpdateMacros(self):
|
|
1015
1026
|
for name, node in await self.hive.open(('cortex', 'storm', 'macros')):
|
|
1016
1027
|
|
|
@@ -1045,6 +1056,9 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1045
1056
|
|
|
1046
1057
|
def getStormMacro(self, name, user=None):
|
|
1047
1058
|
|
|
1059
|
+
if not name:
|
|
1060
|
+
raise s_exc.BadArg(mesg=f'Macro names must be at least 1 character long')
|
|
1061
|
+
|
|
1048
1062
|
if len(name) > 491:
|
|
1049
1063
|
raise s_exc.BadArg(mesg='Macro names may only be up to 491 chars.')
|
|
1050
1064
|
|
|
@@ -1135,6 +1149,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1135
1149
|
raise s_exc.BadArg(mesg=f'Duplicate macro name: {name}')
|
|
1136
1150
|
|
|
1137
1151
|
self.slab.put(name.encode(), s_msgpack.en(mdef), db=self.macrodb)
|
|
1152
|
+
await self.feedBeholder('storm:macro:add', {'macro': mdef})
|
|
1138
1153
|
return mdef
|
|
1139
1154
|
|
|
1140
1155
|
async def delStormMacro(self, name, user=None):
|
|
@@ -1146,9 +1161,15 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1146
1161
|
|
|
1147
1162
|
@s_nexus.Pusher.onPush('storm:macro:del')
|
|
1148
1163
|
async def _delStormMacro(self, name):
|
|
1164
|
+
if not name:
|
|
1165
|
+
raise s_exc.BadArg(mesg=f'Macro names must be at least 1 character long')
|
|
1166
|
+
|
|
1149
1167
|
byts = self.slab.pop(name.encode(), db=self.macrodb)
|
|
1168
|
+
|
|
1150
1169
|
if byts is not None:
|
|
1151
|
-
|
|
1170
|
+
macro = s_msgpack.un(byts)
|
|
1171
|
+
await self.feedBeholder('storm:macro:del', {'name': name, 'iden': macro.get('iden')})
|
|
1172
|
+
return macro
|
|
1152
1173
|
|
|
1153
1174
|
async def modStormMacro(self, name, info, user=None):
|
|
1154
1175
|
if user is not None:
|
|
@@ -1178,6 +1199,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1178
1199
|
else:
|
|
1179
1200
|
self.slab.put(name.encode(), s_msgpack.en(mdef), db=self.macrodb)
|
|
1180
1201
|
|
|
1202
|
+
await self.feedBeholder('storm:macro:mod', {'macro': mdef, 'info': info})
|
|
1181
1203
|
return mdef
|
|
1182
1204
|
|
|
1183
1205
|
async def setStormMacroPerm(self, name, scope, iden, level, user=None):
|
|
@@ -1196,6 +1218,14 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1196
1218
|
reqValidStormMacro(mdef)
|
|
1197
1219
|
|
|
1198
1220
|
self.slab.put(name.encode(), s_msgpack.en(mdef), db=self.macrodb)
|
|
1221
|
+
|
|
1222
|
+
info = {
|
|
1223
|
+
'scope': scope,
|
|
1224
|
+
'iden': iden,
|
|
1225
|
+
'level': level
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
await self.feedBeholder('storm:macro:set:perm', {'macro': mdef, 'info': info})
|
|
1199
1229
|
return mdef
|
|
1200
1230
|
|
|
1201
1231
|
async def getStormMacros(self, user=None):
|
|
@@ -1395,6 +1425,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1395
1425
|
|
|
1396
1426
|
await self._bumpCellVers('cortex:defaults', (
|
|
1397
1427
|
(1, self._addAllLayrRead),
|
|
1428
|
+
(2, self._viewNomergeToProtected),
|
|
1398
1429
|
))
|
|
1399
1430
|
|
|
1400
1431
|
async def _addAllLayrRead(self):
|
|
@@ -1447,6 +1478,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1447
1478
|
async def initServiceActive(self):
|
|
1448
1479
|
|
|
1449
1480
|
await self.stormdmons.start()
|
|
1481
|
+
await self.agenda.clearRunningStatus()
|
|
1450
1482
|
|
|
1451
1483
|
for view in self.views.values():
|
|
1452
1484
|
await view.initTrigTask()
|
|
@@ -1472,19 +1504,28 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1472
1504
|
|
|
1473
1505
|
async def initStormPool(self):
|
|
1474
1506
|
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1507
|
+
try:
|
|
1508
|
+
|
|
1509
|
+
byts = self.slab.get(b'storm:pool', db='cell:conf')
|
|
1510
|
+
if byts is None:
|
|
1511
|
+
return
|
|
1478
1512
|
|
|
1479
|
-
|
|
1513
|
+
url, opts = s_msgpack.un(byts)
|
|
1480
1514
|
|
|
1481
|
-
|
|
1482
|
-
|
|
1515
|
+
self.stormpoolurl = url
|
|
1516
|
+
self.stormpoolopts = opts
|
|
1483
1517
|
|
|
1484
|
-
|
|
1518
|
+
async def onlink(proxy, urlinfo):
|
|
1519
|
+
_url = s_urlhelp.sanitizeUrl(s_telepath.zipurl(urlinfo))
|
|
1520
|
+
logger.debug(f'Stormpool client connected to {_url}')
|
|
1485
1521
|
|
|
1486
|
-
|
|
1487
|
-
|
|
1522
|
+
self.stormpool = await s_telepath.open(url, onlink=onlink)
|
|
1523
|
+
|
|
1524
|
+
# make this one a fini weakref vs the fini() handler
|
|
1525
|
+
self.onfini(self.stormpool)
|
|
1526
|
+
|
|
1527
|
+
except Exception as e: # pragma: no cover
|
|
1528
|
+
logger.exception(f'Error starting stormpool, it will not be available: {e}')
|
|
1488
1529
|
|
|
1489
1530
|
async def finiStormPool(self):
|
|
1490
1531
|
|
|
@@ -3478,14 +3519,12 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
3478
3519
|
buid = s_common.uhex(iden)
|
|
3479
3520
|
async with await self.snap(user=user) as snap:
|
|
3480
3521
|
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
if node is None:
|
|
3485
|
-
raise s_exc.NoSuchIden(iden=iden)
|
|
3522
|
+
node = await snap.getNodeByBuid(buid)
|
|
3523
|
+
if node is None:
|
|
3524
|
+
raise s_exc.NoSuchIden(iden=iden)
|
|
3486
3525
|
|
|
3487
|
-
|
|
3488
|
-
|
|
3526
|
+
await node.addTag(tag, valu=valu)
|
|
3527
|
+
return node.pack()
|
|
3489
3528
|
|
|
3490
3529
|
async def addNode(self, user, form, valu, props=None):
|
|
3491
3530
|
|
|
@@ -3505,14 +3544,12 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
3505
3544
|
|
|
3506
3545
|
async with await self.snap(user=user) as snap:
|
|
3507
3546
|
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
if node is None:
|
|
3512
|
-
raise s_exc.NoSuchIden(iden=iden)
|
|
3547
|
+
node = await snap.getNodeByBuid(buid)
|
|
3548
|
+
if node is None:
|
|
3549
|
+
raise s_exc.NoSuchIden(iden=iden)
|
|
3513
3550
|
|
|
3514
|
-
|
|
3515
|
-
|
|
3551
|
+
await node.delTag(tag)
|
|
3552
|
+
return node.pack()
|
|
3516
3553
|
|
|
3517
3554
|
async def _onCoreFini(self):
|
|
3518
3555
|
'''
|
|
@@ -4130,7 +4167,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
4130
4167
|
@s_nexus.Pusher.onPushAuto('http:api:mod')
|
|
4131
4168
|
async def modHttpExtApi(self, iden, name, valu):
|
|
4132
4169
|
# Created, Creator, Updated are not mutable
|
|
4133
|
-
if name in ('name', 'desc', 'runas', 'methods', 'authenticated', 'perms', 'readonly', 'vars'):
|
|
4170
|
+
if name in ('name', 'desc', 'runas', 'methods', 'authenticated', 'pool', 'perms', 'readonly', 'vars'):
|
|
4134
4171
|
# Schema takes care of these values
|
|
4135
4172
|
pass
|
|
4136
4173
|
elif name == 'owner':
|
|
@@ -4447,6 +4484,10 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
4447
4484
|
if view is None:
|
|
4448
4485
|
raise s_exc.NoSuchView(mesg=f'No such view {iden=}', iden=iden)
|
|
4449
4486
|
|
|
4487
|
+
if view.info.get('protected'):
|
|
4488
|
+
mesg = f'Cannot delete view ({iden}) that has protected set.'
|
|
4489
|
+
raise s_exc.CantDelView(mesg=mesg)
|
|
4490
|
+
|
|
4450
4491
|
return await self._push('view:del', iden)
|
|
4451
4492
|
|
|
4452
4493
|
@s_nexus.Pusher.onPush('view:del')
|
|
@@ -5280,12 +5321,14 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
5280
5321
|
return mirropts
|
|
5281
5322
|
|
|
5282
5323
|
async def _getMirrorProxy(self):
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5324
|
+
|
|
5325
|
+
if self.stormpool is None: # pragma: no cover
|
|
5326
|
+
return None
|
|
5327
|
+
|
|
5328
|
+
if self.stormpool.size() == 0:
|
|
5329
|
+
logger.warning('Storm query mirror pool is empty, running query locally.')
|
|
5286
5330
|
return None
|
|
5287
5331
|
|
|
5288
|
-
proxy = None
|
|
5289
5332
|
try:
|
|
5290
5333
|
timeout = self.stormpoolopts.get('timeout:connection')
|
|
5291
5334
|
proxy = await self.stormpool.proxy(timeout=timeout)
|
|
@@ -5293,10 +5336,12 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
5293
5336
|
if proxyname is not None and proxyname == self.ahasvcname:
|
|
5294
5337
|
# we are part of the pool and were selected. Convert to local use.
|
|
5295
5338
|
return None
|
|
5339
|
+
|
|
5340
|
+
return proxy
|
|
5341
|
+
|
|
5296
5342
|
except (TimeoutError, s_exc.IsFini):
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
return proxy
|
|
5343
|
+
logger.warning('Timeout waiting for pool mirror, running query locally.')
|
|
5344
|
+
return None
|
|
5300
5345
|
|
|
5301
5346
|
async def storm(self, text, opts=None):
|
|
5302
5347
|
|
|
@@ -5767,16 +5812,15 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
5767
5812
|
|
|
5768
5813
|
async def _initCoreMods(self):
|
|
5769
5814
|
|
|
5770
|
-
|
|
5771
|
-
for ctor, modu in list(self.modules.items()):
|
|
5815
|
+
for ctor, modu in list(self.modules.items()):
|
|
5772
5816
|
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5817
|
+
try:
|
|
5818
|
+
await s_coro.ornot(modu.initCoreModule)
|
|
5819
|
+
except asyncio.CancelledError: # pragma: no cover TODO: remove once >= py 3.8 only
|
|
5820
|
+
raise
|
|
5821
|
+
except Exception:
|
|
5822
|
+
logger.exception(f'module initCoreModule failed: {ctor}')
|
|
5823
|
+
self.modules.pop(ctor, None)
|
|
5780
5824
|
|
|
5781
5825
|
def _loadCoreModule(self, ctor, conf=None):
|
|
5782
5826
|
|
|
@@ -6033,6 +6077,9 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
6033
6077
|
elif name == 'doc':
|
|
6034
6078
|
appt.doc = str(valu)
|
|
6035
6079
|
|
|
6080
|
+
elif name == 'pool':
|
|
6081
|
+
appt.pool = bool(valu)
|
|
6082
|
+
|
|
6036
6083
|
else:
|
|
6037
6084
|
mesg = f'editCronJob name {name} is not supported for editing.'
|
|
6038
6085
|
raise s_exc.BadArg(mesg=mesg)
|
synapse/datamodel.py
CHANGED
|
@@ -873,10 +873,42 @@ class Model:
|
|
|
873
873
|
for ifname in form.type.info.get('interfaces', ()):
|
|
874
874
|
self._addFormIface(form, ifname)
|
|
875
875
|
|
|
876
|
+
self._checkFormDisplay(form)
|
|
877
|
+
|
|
876
878
|
self.formprefixcache.clear()
|
|
877
879
|
|
|
878
880
|
return form
|
|
879
881
|
|
|
882
|
+
def _checkFormDisplay(self, form):
|
|
883
|
+
|
|
884
|
+
formtype = self.types.get(form.full)
|
|
885
|
+
|
|
886
|
+
display = formtype.info.get('display')
|
|
887
|
+
if display is None:
|
|
888
|
+
return
|
|
889
|
+
|
|
890
|
+
for column in display.get('columns', ()):
|
|
891
|
+
coltype = column.get('type')
|
|
892
|
+
colopts = column.get('opts')
|
|
893
|
+
|
|
894
|
+
if coltype == 'prop':
|
|
895
|
+
curf = form
|
|
896
|
+
propname = colopts.get('name')
|
|
897
|
+
parts = propname.split('::')
|
|
898
|
+
|
|
899
|
+
for partname in parts:
|
|
900
|
+
prop = curf.prop(partname)
|
|
901
|
+
if prop is None:
|
|
902
|
+
mesg = (f'Form {form.name} defines prop column {propname}'
|
|
903
|
+
f' but {curf.full} has no property named {partname}.')
|
|
904
|
+
raise s_exc.BadFormDef(mesg=mesg)
|
|
905
|
+
|
|
906
|
+
curf = self.form(prop.type.name)
|
|
907
|
+
|
|
908
|
+
else:
|
|
909
|
+
mesg = f'Form {form.name} defines column with invalid type ({coltype}).'
|
|
910
|
+
raise s_exc.BadFormDef(mesg=mesg)
|
|
911
|
+
|
|
880
912
|
def delForm(self, formname):
|
|
881
913
|
|
|
882
914
|
form = self.forms.get(formname)
|
synapse/exc.py
CHANGED
|
@@ -145,6 +145,7 @@ class CantDelForm(SynErr): pass
|
|
|
145
145
|
class CantDelProp(SynErr): pass
|
|
146
146
|
class CantDelType(SynErr): pass
|
|
147
147
|
class CantDelUniv(SynErr): pass
|
|
148
|
+
class CantDelView(SynErr): pass
|
|
148
149
|
class CantMergeView(SynErr): pass
|
|
149
150
|
class CantRevLayer(SynErr): pass
|
|
150
151
|
class CliFini(SynErr):
|