synapse 2.196.0__py311-none-any.whl → 2.198.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 +3 -0
- synapse/common.py +3 -0
- synapse/cortex.py +13 -11
- synapse/cryotank.py +2 -2
- synapse/lib/aha.py +3 -0
- synapse/lib/ast.py +277 -165
- synapse/lib/auth.py +39 -11
- synapse/lib/cell.py +24 -6
- synapse/lib/config.py +3 -3
- synapse/lib/hive.py +2 -1
- synapse/lib/hiveauth.py +10 -1
- synapse/lib/jsonstor.py +6 -5
- synapse/lib/layer.py +6 -5
- synapse/lib/multislabseqn.py +2 -2
- synapse/lib/node.py +10 -4
- synapse/lib/parser.py +46 -21
- synapse/lib/schemas.py +491 -1
- synapse/lib/snap.py +68 -26
- synapse/lib/storm.lark +13 -11
- synapse/lib/storm.py +13 -395
- synapse/lib/storm_format.py +3 -2
- synapse/lib/stormlib/graph.py +0 -61
- synapse/lib/stormlib/index.py +52 -0
- synapse/lib/stormtypes.py +16 -5
- synapse/lib/task.py +13 -2
- synapse/lib/urlhelp.py +1 -1
- synapse/lib/version.py +2 -2
- synapse/models/doc.py +62 -0
- synapse/models/infotech.py +18 -0
- synapse/models/orgs.py +6 -4
- synapse/models/risk.py +9 -0
- synapse/models/syn.py +18 -2
- synapse/tests/files/stormpkg/badendpoints.yaml +7 -0
- synapse/tests/files/stormpkg/testpkg.yaml +8 -0
- synapse/tests/test_cortex.py +108 -0
- synapse/tests/test_datamodel.py +7 -0
- synapse/tests/test_lib_aha.py +12 -42
- synapse/tests/test_lib_ast.py +57 -0
- synapse/tests/test_lib_auth.py +143 -2
- synapse/tests/test_lib_boss.py +15 -6
- synapse/tests/test_lib_cell.py +43 -0
- synapse/tests/test_lib_grammar.py +54 -2
- synapse/tests/test_lib_lmdbslab.py +24 -0
- synapse/tests/test_lib_storm.py +20 -0
- synapse/tests/test_lib_stormlib_index.py +39 -0
- synapse/tests/test_lib_stormlib_macro.py +3 -3
- synapse/tests/test_lib_stormtypes.py +14 -2
- synapse/tests/test_lib_task.py +31 -13
- synapse/tests/test_model_doc.py +38 -0
- synapse/tests/test_model_infotech.py +13 -0
- synapse/tests/test_model_orgs.py +7 -0
- synapse/tests/test_model_risk.py +6 -0
- synapse/tests/test_model_syn.py +58 -0
- synapse/tests/test_tools_genpkg.py +10 -0
- synapse/tools/genpkg.py +2 -2
- synapse/tools/hive/load.py +1 -0
- {synapse-2.196.0.dist-info → synapse-2.198.0.dist-info}/METADATA +1 -1
- {synapse-2.196.0.dist-info → synapse-2.198.0.dist-info}/RECORD +61 -58
- {synapse-2.196.0.dist-info → synapse-2.198.0.dist-info}/LICENSE +0 -0
- {synapse-2.196.0.dist-info → synapse-2.198.0.dist-info}/WHEEL +0 -0
- {synapse-2.196.0.dist-info → synapse-2.198.0.dist-info}/top_level.txt +0 -0
synapse/lib/ast.py
CHANGED
|
@@ -62,7 +62,7 @@ class AstNode:
|
|
|
62
62
|
|
|
63
63
|
def getPosInfo(self):
|
|
64
64
|
return {
|
|
65
|
-
'hash':
|
|
65
|
+
'hash': s_common.queryhash(self.astinfo.text),
|
|
66
66
|
'lines': (self.astinfo.sline, self.astinfo.eline),
|
|
67
67
|
'columns': (self.astinfo.scol, self.astinfo.ecol),
|
|
68
68
|
'offsets': (self.astinfo.soff, self.astinfo.eoff),
|
|
@@ -699,7 +699,92 @@ class SubGraph:
|
|
|
699
699
|
yield node, path
|
|
700
700
|
|
|
701
701
|
class Oper(AstNode):
|
|
702
|
-
|
|
702
|
+
|
|
703
|
+
async def yieldFromValu(self, runt, valu, vkid):
|
|
704
|
+
|
|
705
|
+
viewiden = runt.snap.view.iden
|
|
706
|
+
|
|
707
|
+
# there is nothing in None... ;)
|
|
708
|
+
if valu is None:
|
|
709
|
+
return
|
|
710
|
+
|
|
711
|
+
# a little DWIM on what we get back...
|
|
712
|
+
# ( most common case will be stormtypes libs agenr -> iden|buid )
|
|
713
|
+
# buid list -> nodes
|
|
714
|
+
if isinstance(valu, bytes):
|
|
715
|
+
node = await runt.snap.getNodeByBuid(valu)
|
|
716
|
+
if node is not None:
|
|
717
|
+
yield node
|
|
718
|
+
|
|
719
|
+
return
|
|
720
|
+
|
|
721
|
+
# iden list -> nodes
|
|
722
|
+
if isinstance(valu, str):
|
|
723
|
+
try:
|
|
724
|
+
buid = s_common.uhex(valu)
|
|
725
|
+
except binascii.Error:
|
|
726
|
+
mesg = 'Yield string must be iden in hexdecimal. Got: %r' % (valu,)
|
|
727
|
+
raise vkid.addExcInfo(s_exc.BadLiftValu(mesg=mesg))
|
|
728
|
+
|
|
729
|
+
node = await runt.snap.getNodeByBuid(buid)
|
|
730
|
+
if node is not None:
|
|
731
|
+
yield node
|
|
732
|
+
|
|
733
|
+
return
|
|
734
|
+
|
|
735
|
+
if isinstance(valu, types.AsyncGeneratorType):
|
|
736
|
+
try:
|
|
737
|
+
async for item in valu:
|
|
738
|
+
async for node in self.yieldFromValu(runt, item, vkid):
|
|
739
|
+
yield node
|
|
740
|
+
finally:
|
|
741
|
+
await valu.aclose()
|
|
742
|
+
return
|
|
743
|
+
|
|
744
|
+
if isinstance(valu, types.GeneratorType):
|
|
745
|
+
try:
|
|
746
|
+
for item in valu:
|
|
747
|
+
async for node in self.yieldFromValu(runt, item, vkid):
|
|
748
|
+
yield node
|
|
749
|
+
finally:
|
|
750
|
+
valu.close()
|
|
751
|
+
return
|
|
752
|
+
|
|
753
|
+
if isinstance(valu, (list, tuple, set)):
|
|
754
|
+
for item in valu:
|
|
755
|
+
async for node in self.yieldFromValu(runt, item, vkid):
|
|
756
|
+
yield node
|
|
757
|
+
return
|
|
758
|
+
|
|
759
|
+
if isinstance(valu, s_stormtypes.Node):
|
|
760
|
+
valu = valu.valu
|
|
761
|
+
if valu.snap.view.iden != viewiden:
|
|
762
|
+
mesg = f'Node is not from the current view. Node {valu.iden()} is from {valu.snap.view.iden} expected {viewiden}'
|
|
763
|
+
raise vkid.addExcInfo(s_exc.BadLiftValu(mesg=mesg))
|
|
764
|
+
yield valu
|
|
765
|
+
return
|
|
766
|
+
|
|
767
|
+
if isinstance(valu, s_node.Node):
|
|
768
|
+
if valu.snap.view.iden != viewiden:
|
|
769
|
+
mesg = f'Node is not from the current view. Node {valu.iden()} is from {valu.snap.view.iden} expected {viewiden}'
|
|
770
|
+
raise vkid.addExcInfo(s_exc.BadLiftValu(mesg=mesg))
|
|
771
|
+
yield valu
|
|
772
|
+
return
|
|
773
|
+
|
|
774
|
+
if isinstance(valu, (s_stormtypes.List, s_stormtypes.Set)):
|
|
775
|
+
for item in valu.valu:
|
|
776
|
+
async for node in self.yieldFromValu(runt, item, vkid):
|
|
777
|
+
yield node
|
|
778
|
+
return
|
|
779
|
+
|
|
780
|
+
if isinstance(valu, s_stormtypes.Prim):
|
|
781
|
+
async with contextlib.aclosing(valu.nodes()) as genr:
|
|
782
|
+
async for node in genr:
|
|
783
|
+
if node.snap.view.iden != viewiden:
|
|
784
|
+
mesg = f'Node is not from the current view. Node {node.iden()} is from {node.snap.view.iden} expected {viewiden}'
|
|
785
|
+
raise vkid.addExcInfo(s_exc.BadLiftValu(mesg=mesg))
|
|
786
|
+
yield node
|
|
787
|
+
return
|
|
703
788
|
|
|
704
789
|
class SubQuery(Oper):
|
|
705
790
|
|
|
@@ -1534,106 +1619,21 @@ class YieldValu(Oper):
|
|
|
1534
1619
|
async def run(self, runt, genr):
|
|
1535
1620
|
|
|
1536
1621
|
node = None
|
|
1622
|
+
vkid = self.kids[0]
|
|
1537
1623
|
|
|
1538
1624
|
async for node, path in genr:
|
|
1539
|
-
valu = await
|
|
1540
|
-
async with contextlib.aclosing(self.yieldFromValu(runt, valu)) as agen:
|
|
1625
|
+
valu = await vkid.compute(runt, path)
|
|
1626
|
+
async with contextlib.aclosing(self.yieldFromValu(runt, valu, vkid)) as agen:
|
|
1541
1627
|
async for subn in agen:
|
|
1542
1628
|
yield subn, runt.initPath(subn)
|
|
1543
1629
|
yield node, path
|
|
1544
1630
|
|
|
1545
1631
|
if node is None and self.kids[0].isRuntSafe(runt):
|
|
1546
|
-
valu = await
|
|
1547
|
-
async with contextlib.aclosing(self.yieldFromValu(runt, valu)) as agen:
|
|
1632
|
+
valu = await vkid.compute(runt, None)
|
|
1633
|
+
async with contextlib.aclosing(self.yieldFromValu(runt, valu, vkid)) as agen:
|
|
1548
1634
|
async for subn in agen:
|
|
1549
1635
|
yield subn, runt.initPath(subn)
|
|
1550
1636
|
|
|
1551
|
-
async def yieldFromValu(self, runt, valu):
|
|
1552
|
-
|
|
1553
|
-
viewiden = runt.snap.view.iden
|
|
1554
|
-
|
|
1555
|
-
# there is nothing in None... ;)
|
|
1556
|
-
if valu is None:
|
|
1557
|
-
return
|
|
1558
|
-
|
|
1559
|
-
# a little DWIM on what we get back...
|
|
1560
|
-
# ( most common case will be stormtypes libs agenr -> iden|buid )
|
|
1561
|
-
# buid list -> nodes
|
|
1562
|
-
if isinstance(valu, bytes):
|
|
1563
|
-
node = await runt.snap.getNodeByBuid(valu)
|
|
1564
|
-
if node is not None:
|
|
1565
|
-
yield node
|
|
1566
|
-
|
|
1567
|
-
return
|
|
1568
|
-
|
|
1569
|
-
# iden list -> nodes
|
|
1570
|
-
if isinstance(valu, str):
|
|
1571
|
-
try:
|
|
1572
|
-
buid = s_common.uhex(valu)
|
|
1573
|
-
except binascii.Error:
|
|
1574
|
-
mesg = 'Yield string must be iden in hexdecimal. Got: %r' % (valu,)
|
|
1575
|
-
raise self.kids[0].addExcInfo(s_exc.BadLiftValu(mesg=mesg))
|
|
1576
|
-
|
|
1577
|
-
node = await runt.snap.getNodeByBuid(buid)
|
|
1578
|
-
if node is not None:
|
|
1579
|
-
yield node
|
|
1580
|
-
|
|
1581
|
-
return
|
|
1582
|
-
|
|
1583
|
-
if isinstance(valu, types.AsyncGeneratorType):
|
|
1584
|
-
try:
|
|
1585
|
-
async for item in valu:
|
|
1586
|
-
async for node in self.yieldFromValu(runt, item):
|
|
1587
|
-
yield node
|
|
1588
|
-
finally:
|
|
1589
|
-
await valu.aclose()
|
|
1590
|
-
return
|
|
1591
|
-
|
|
1592
|
-
if isinstance(valu, types.GeneratorType):
|
|
1593
|
-
try:
|
|
1594
|
-
for item in valu:
|
|
1595
|
-
async for node in self.yieldFromValu(runt, item):
|
|
1596
|
-
yield node
|
|
1597
|
-
finally:
|
|
1598
|
-
valu.close()
|
|
1599
|
-
return
|
|
1600
|
-
|
|
1601
|
-
if isinstance(valu, (list, tuple, set)):
|
|
1602
|
-
for item in valu:
|
|
1603
|
-
async for node in self.yieldFromValu(runt, item):
|
|
1604
|
-
yield node
|
|
1605
|
-
return
|
|
1606
|
-
|
|
1607
|
-
if isinstance(valu, s_stormtypes.Node):
|
|
1608
|
-
valu = valu.valu
|
|
1609
|
-
if valu.snap.view.iden != viewiden:
|
|
1610
|
-
mesg = f'Node is not from the current view. Node {valu.iden()} is from {valu.snap.view.iden} expected {viewiden}'
|
|
1611
|
-
raise s_exc.BadLiftValu(mesg=mesg)
|
|
1612
|
-
yield valu
|
|
1613
|
-
return
|
|
1614
|
-
|
|
1615
|
-
if isinstance(valu, s_node.Node):
|
|
1616
|
-
if valu.snap.view.iden != viewiden:
|
|
1617
|
-
mesg = f'Node is not from the current view. Node {valu.iden()} is from {valu.snap.view.iden} expected {viewiden}'
|
|
1618
|
-
raise s_exc.BadLiftValu(mesg=mesg)
|
|
1619
|
-
yield valu
|
|
1620
|
-
return
|
|
1621
|
-
|
|
1622
|
-
if isinstance(valu, (s_stormtypes.List, s_stormtypes.Set)):
|
|
1623
|
-
for item in valu.valu:
|
|
1624
|
-
async for node in self.yieldFromValu(runt, item):
|
|
1625
|
-
yield node
|
|
1626
|
-
return
|
|
1627
|
-
|
|
1628
|
-
if isinstance(valu, s_stormtypes.Prim):
|
|
1629
|
-
async with contextlib.aclosing(valu.nodes()) as genr:
|
|
1630
|
-
async for node in genr:
|
|
1631
|
-
if node.snap.view.iden != viewiden:
|
|
1632
|
-
mesg = f'Node is not from the current view. Node {node.iden()} is from {node.snap.view.iden} expected {viewiden}'
|
|
1633
|
-
raise s_exc.BadLiftValu(mesg=mesg)
|
|
1634
|
-
yield node
|
|
1635
|
-
return
|
|
1636
|
-
|
|
1637
1637
|
class LiftTag(LiftOper):
|
|
1638
1638
|
|
|
1639
1639
|
async def lift(self, runt, path):
|
|
@@ -4370,6 +4370,83 @@ class EditPropSet(Edit):
|
|
|
4370
4370
|
|
|
4371
4371
|
await asyncio.sleep(0)
|
|
4372
4372
|
|
|
4373
|
+
class EditPropSetMulti(Edit):
|
|
4374
|
+
|
|
4375
|
+
async def run(self, runt, genr):
|
|
4376
|
+
|
|
4377
|
+
self.reqNotReadOnly(runt)
|
|
4378
|
+
|
|
4379
|
+
rval = self.kids[2]
|
|
4380
|
+
oper = await self.kids[1].compute(runt, None)
|
|
4381
|
+
|
|
4382
|
+
isadd = '+' in oper
|
|
4383
|
+
excignore = (s_exc.BadTypeValu,) if '?' in oper else ()
|
|
4384
|
+
|
|
4385
|
+
async for node, path in genr:
|
|
4386
|
+
|
|
4387
|
+
propname = await self.kids[0].compute(runt, path)
|
|
4388
|
+
name = await tostr(propname)
|
|
4389
|
+
|
|
4390
|
+
prop = node.form.props.get(name)
|
|
4391
|
+
if prop is None:
|
|
4392
|
+
if (exc := await s_stormtypes.typeerr(propname, str)) is None:
|
|
4393
|
+
exc = s_exc.NoSuchProp.init(f'{node.form.name}:{name}')
|
|
4394
|
+
|
|
4395
|
+
raise self.kids[0].addExcInfo(exc)
|
|
4396
|
+
|
|
4397
|
+
runt.confirmPropSet(prop)
|
|
4398
|
+
|
|
4399
|
+
if not prop.type.isarray:
|
|
4400
|
+
mesg = f'Property set using ({oper}) is only valid on arrays.'
|
|
4401
|
+
exc = s_exc.StormRuntimeError(mesg=mesg)
|
|
4402
|
+
raise self.kids[0].addExcInfo(exc)
|
|
4403
|
+
|
|
4404
|
+
if isinstance(rval, SubQuery):
|
|
4405
|
+
valu = await rval.compute_array(runt, path)
|
|
4406
|
+
else:
|
|
4407
|
+
valu = await rval.compute(runt, path)
|
|
4408
|
+
|
|
4409
|
+
if valu is None:
|
|
4410
|
+
yield node, path
|
|
4411
|
+
await asyncio.sleep(0)
|
|
4412
|
+
continue
|
|
4413
|
+
|
|
4414
|
+
atyp = prop.type.arraytype
|
|
4415
|
+
isndef = isinstance(atyp, s_types.Ndef)
|
|
4416
|
+
valu = await s_stormtypes.tostor(valu, isndef=isndef)
|
|
4417
|
+
|
|
4418
|
+
if (arry := node.get(name)) is None:
|
|
4419
|
+
arry = ()
|
|
4420
|
+
|
|
4421
|
+
arry = list(arry)
|
|
4422
|
+
|
|
4423
|
+
try:
|
|
4424
|
+
for item in valu:
|
|
4425
|
+
await asyncio.sleep(0)
|
|
4426
|
+
|
|
4427
|
+
try:
|
|
4428
|
+
norm, info = atyp.norm(item)
|
|
4429
|
+
except excignore:
|
|
4430
|
+
continue
|
|
4431
|
+
|
|
4432
|
+
if isadd:
|
|
4433
|
+
arry.append(norm)
|
|
4434
|
+
else:
|
|
4435
|
+
try:
|
|
4436
|
+
arry.remove(norm)
|
|
4437
|
+
except ValueError:
|
|
4438
|
+
pass
|
|
4439
|
+
|
|
4440
|
+
except TypeError:
|
|
4441
|
+
styp = await s_stormtypes.totype(valu, basetypes=True)
|
|
4442
|
+
mesg = f"'{styp}' object is not iterable: {s_common.trimText(repr(valu))}"
|
|
4443
|
+
raise rval.addExcInfo(s_exc.StormRuntimeError(mesg=mesg, type=styp)) from None
|
|
4444
|
+
|
|
4445
|
+
await node.set(name, arry)
|
|
4446
|
+
|
|
4447
|
+
yield node, path
|
|
4448
|
+
await asyncio.sleep(0)
|
|
4449
|
+
|
|
4373
4450
|
class EditPropDel(Edit):
|
|
4374
4451
|
|
|
4375
4452
|
async def run(self, runt, genr):
|
|
@@ -4578,17 +4655,27 @@ class EditEdgeAdd(Edit):
|
|
|
4578
4655
|
|
|
4579
4656
|
self.reqNotReadOnly(runt)
|
|
4580
4657
|
|
|
4581
|
-
|
|
4582
|
-
|
|
4658
|
+
constverb = False
|
|
4659
|
+
if self.kids[0].isconst:
|
|
4660
|
+
constverb = True
|
|
4661
|
+
verb = await tostr(await self.kids[0].compute(runt, None))
|
|
4662
|
+
runt.layerConfirm(('node', 'edge', 'add', verb))
|
|
4663
|
+
else:
|
|
4664
|
+
hits = set()
|
|
4665
|
+
def allowed(x):
|
|
4666
|
+
if x in hits:
|
|
4667
|
+
return
|
|
4583
4668
|
|
|
4584
|
-
|
|
4669
|
+
runt.layerConfirm(('node', 'edge', 'add', x))
|
|
4670
|
+
hits.add(x)
|
|
4585
4671
|
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
return
|
|
4672
|
+
isvar = False
|
|
4673
|
+
vkid = self.kids[1]
|
|
4589
4674
|
|
|
4590
|
-
|
|
4591
|
-
|
|
4675
|
+
if not isinstance(vkid, SubQuery):
|
|
4676
|
+
isvar = True
|
|
4677
|
+
else:
|
|
4678
|
+
query = vkid.kids[0]
|
|
4592
4679
|
|
|
4593
4680
|
async for node, path in genr:
|
|
4594
4681
|
|
|
@@ -4596,38 +4683,44 @@ class EditEdgeAdd(Edit):
|
|
|
4596
4683
|
mesg = f'Edges cannot be used with runt nodes: {node.form.full}'
|
|
4597
4684
|
raise self.addExcInfo(s_exc.IsRuntForm(mesg=mesg, form=node.form.full))
|
|
4598
4685
|
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4686
|
+
if not constverb:
|
|
4687
|
+
verb = await tostr(await self.kids[0].compute(runt, path))
|
|
4688
|
+
allowed(verb)
|
|
4689
|
+
|
|
4690
|
+
if isvar:
|
|
4691
|
+
valu = await vkid.compute(runt, path)
|
|
4692
|
+
async with contextlib.aclosing(self.yieldFromValu(runt, valu, vkid)) as agen:
|
|
4693
|
+
if self.n2:
|
|
4694
|
+
iden = node.iden()
|
|
4695
|
+
async for subn in agen:
|
|
4696
|
+
await subn.addEdge(verb, iden, extra=self.addExcInfo)
|
|
4697
|
+
else:
|
|
4698
|
+
async with node.snap.getEditor() as editor:
|
|
4699
|
+
proto = editor.loadNode(node)
|
|
4700
|
+
async for subn in agen:
|
|
4701
|
+
if subn.form.isrunt:
|
|
4702
|
+
mesg = f'Edges cannot be used with runt nodes: {subn.form.full}'
|
|
4703
|
+
raise self.addExcInfo(s_exc.IsRuntForm(mesg=mesg, form=subn.form.full))
|
|
4704
|
+
|
|
4705
|
+
await proto.addEdge(verb, subn.iden())
|
|
4706
|
+
await asyncio.sleep(0)
|
|
4617
4707
|
|
|
4708
|
+
else:
|
|
4709
|
+
async with runt.getSubRuntime(query) as subr:
|
|
4710
|
+
if self.n2:
|
|
4711
|
+
iden = node.iden()
|
|
4618
4712
|
async for subn, subp in subr.execute():
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
proto.edges.clear()
|
|
4713
|
+
await subn.addEdge(verb, iden, extra=self.addExcInfo)
|
|
4714
|
+
else:
|
|
4715
|
+
async with node.snap.getEditor() as editor:
|
|
4716
|
+
proto = editor.loadNode(node)
|
|
4717
|
+
async for subn, subp in subr.execute():
|
|
4718
|
+
if subn.form.isrunt:
|
|
4719
|
+
mesg = f'Edges cannot be used with runt nodes: {subn.form.full}'
|
|
4720
|
+
raise self.addExcInfo(s_exc.IsRuntForm(mesg=mesg, form=subn.form.full))
|
|
4721
|
+
|
|
4722
|
+
await proto.addEdge(verb, subn.iden())
|
|
4723
|
+
await asyncio.sleep(0)
|
|
4631
4724
|
|
|
4632
4725
|
yield node, path
|
|
4633
4726
|
|
|
@@ -4641,16 +4734,27 @@ class EditEdgeDel(Edit):
|
|
|
4641
4734
|
|
|
4642
4735
|
self.reqNotReadOnly(runt)
|
|
4643
4736
|
|
|
4644
|
-
|
|
4737
|
+
isvar = False
|
|
4738
|
+
vkid = self.kids[1]
|
|
4645
4739
|
|
|
4646
|
-
|
|
4740
|
+
if not isinstance(vkid, SubQuery):
|
|
4741
|
+
isvar = True
|
|
4742
|
+
else:
|
|
4743
|
+
query = vkid.kids[0]
|
|
4647
4744
|
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4745
|
+
constverb = False
|
|
4746
|
+
if self.kids[0].isconst:
|
|
4747
|
+
constverb = True
|
|
4748
|
+
verb = await tostr(await self.kids[0].compute(runt, None))
|
|
4749
|
+
runt.layerConfirm(('node', 'edge', 'del', verb))
|
|
4750
|
+
else:
|
|
4751
|
+
hits = set()
|
|
4752
|
+
def allowed(x):
|
|
4753
|
+
if x in hits:
|
|
4754
|
+
return
|
|
4651
4755
|
|
|
4652
|
-
|
|
4653
|
-
|
|
4756
|
+
runt.layerConfirm(('node', 'edge', 'del', x))
|
|
4757
|
+
hits.add(x)
|
|
4654
4758
|
|
|
4655
4759
|
async for node, path in genr:
|
|
4656
4760
|
|
|
@@ -4658,36 +4762,44 @@ class EditEdgeDel(Edit):
|
|
|
4658
4762
|
mesg = f'Edges cannot be used with runt nodes: {node.form.full}'
|
|
4659
4763
|
raise self.addExcInfo(s_exc.IsRuntForm(mesg=mesg, form=node.form.full))
|
|
4660
4764
|
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4765
|
+
if not constverb:
|
|
4766
|
+
verb = await tostr(await self.kids[0].compute(runt, path))
|
|
4767
|
+
allowed(verb)
|
|
4768
|
+
|
|
4769
|
+
if isvar:
|
|
4770
|
+
valu = await vkid.compute(runt, path)
|
|
4771
|
+
async with contextlib.aclosing(self.yieldFromValu(runt, valu, vkid)) as agen:
|
|
4772
|
+
if self.n2:
|
|
4773
|
+
iden = node.iden()
|
|
4774
|
+
async for subn in agen:
|
|
4775
|
+
await subn.delEdge(verb, iden, extra=self.addExcInfo)
|
|
4776
|
+
else:
|
|
4777
|
+
async with node.snap.getEditor() as editor:
|
|
4778
|
+
proto = editor.loadNode(node)
|
|
4779
|
+
async for subn in agen:
|
|
4780
|
+
if subn.form.isrunt:
|
|
4781
|
+
mesg = f'Edges cannot be used with runt nodes: {subn.form.full}'
|
|
4782
|
+
raise self.addExcInfo(s_exc.IsRuntForm(mesg=mesg, form=subn.form.full))
|
|
4783
|
+
|
|
4784
|
+
await proto.delEdge(verb, subn.iden())
|
|
4785
|
+
await asyncio.sleep(0)
|
|
4677
4786
|
|
|
4787
|
+
else:
|
|
4788
|
+
async with runt.getSubRuntime(query) as subr:
|
|
4789
|
+
if self.n2:
|
|
4790
|
+
iden = node.iden()
|
|
4678
4791
|
async for subn, subp in subr.execute():
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
proto.edgedels.clear()
|
|
4792
|
+
await subn.delEdge(verb, iden, extra=self.addExcInfo)
|
|
4793
|
+
else:
|
|
4794
|
+
async with node.snap.getEditor() as editor:
|
|
4795
|
+
proto = editor.loadNode(node)
|
|
4796
|
+
async for subn, subp in subr.execute():
|
|
4797
|
+
if subn.form.isrunt:
|
|
4798
|
+
mesg = f'Edges cannot be used with runt nodes: {subn.form.full}'
|
|
4799
|
+
raise self.addExcInfo(s_exc.IsRuntForm(mesg=mesg, form=subn.form.full))
|
|
4800
|
+
|
|
4801
|
+
await proto.delEdge(verb, subn.iden())
|
|
4802
|
+
await asyncio.sleep(0)
|
|
4691
4803
|
|
|
4692
4804
|
yield node, path
|
|
4693
4805
|
|
synapse/lib/auth.py
CHANGED
|
@@ -375,11 +375,32 @@ class Auth(s_nexus.Pusher):
|
|
|
375
375
|
|
|
376
376
|
await self.fire('cell:beholder', **behold)
|
|
377
377
|
|
|
378
|
-
@s_nexus.Pusher.onPushAuto('user:info')
|
|
379
378
|
async def setUserInfo(self, iden, name, valu, gateiden=None, logged=True, mesg=None):
|
|
380
379
|
|
|
381
380
|
user = await self.reqUser(iden)
|
|
382
381
|
|
|
382
|
+
if name == 'locked' and not valu and user.isArchived():
|
|
383
|
+
raise s_exc.BadArg(mesg='Cannot unlock archived user.', user=iden, username=user.name)
|
|
384
|
+
|
|
385
|
+
if name in ('locked', 'archived') and not valu:
|
|
386
|
+
self.checkUserLimit()
|
|
387
|
+
|
|
388
|
+
await self._push('user:info', iden, name, valu, gateiden=gateiden, logged=logged, mesg=mesg)
|
|
389
|
+
|
|
390
|
+
@s_nexus.Pusher.onPush('user:info')
|
|
391
|
+
async def _setUserInfo(self, iden, name, valu, gateiden=None, logged=True, mesg=None):
|
|
392
|
+
user = await self.reqUser(iden)
|
|
393
|
+
|
|
394
|
+
if self.nexsroot and self.nexsroot.cell.nexsvers >= (2, 198):
|
|
395
|
+
# If the nexus version is less than 2.197 then the leader hasn't been upgraded yet and
|
|
396
|
+
# we don't want to get into a schism because we're bouncing edits and the leader is
|
|
397
|
+
# applying them.
|
|
398
|
+
if name == 'locked' and not valu and user.isArchived():
|
|
399
|
+
return
|
|
400
|
+
|
|
401
|
+
if name in ('locked', 'archived') and not valu:
|
|
402
|
+
self.checkUserLimit()
|
|
403
|
+
|
|
383
404
|
if gateiden is not None:
|
|
384
405
|
info = user.genGateInfo(gateiden)
|
|
385
406
|
info[name] = s_msgpack.deepcopy(valu)
|
|
@@ -392,9 +413,6 @@ class Auth(s_nexus.Pusher):
|
|
|
392
413
|
user.info[name] = s_msgpack.deepcopy(valu)
|
|
393
414
|
self.userdefs.set(iden, user.info)
|
|
394
415
|
|
|
395
|
-
if name in ('locked', 'archived') and not valu:
|
|
396
|
-
self.checkUserLimit()
|
|
397
|
-
|
|
398
416
|
if mesg is None:
|
|
399
417
|
mesg = {
|
|
400
418
|
'iden': iden,
|
|
@@ -720,6 +738,16 @@ class Auth(s_nexus.Pusher):
|
|
|
720
738
|
self.roleidenbyname.delete(role.name)
|
|
721
739
|
await self.feedBeholder('role:del', {'iden': iden})
|
|
722
740
|
|
|
741
|
+
def clearAuthCache(self):
|
|
742
|
+
'''
|
|
743
|
+
Clear all auth caches.
|
|
744
|
+
'''
|
|
745
|
+
self.userbyidencache.clear()
|
|
746
|
+
self.useridenbynamecache.clear()
|
|
747
|
+
self.rolebyidencache.clear()
|
|
748
|
+
self.roleidenbynamecache.clear()
|
|
749
|
+
self.authgates.clear()
|
|
750
|
+
|
|
723
751
|
class AuthGate():
|
|
724
752
|
'''
|
|
725
753
|
The storage object for object specific rules for users/roles.
|
|
@@ -975,7 +1003,7 @@ class User(Ruler):
|
|
|
975
1003
|
if nexs:
|
|
976
1004
|
return await self.auth.setUserInfo(self.iden, name, valu, gateiden=gateiden, mesg=mesg)
|
|
977
1005
|
else:
|
|
978
|
-
return await self.auth.
|
|
1006
|
+
return await self.auth._setUserInfo(self.iden, name, valu, gateiden=gateiden, logged=nexs, mesg=mesg)
|
|
979
1007
|
|
|
980
1008
|
async def setName(self, name):
|
|
981
1009
|
return await self.auth.setUserName(self.iden, name)
|
|
@@ -1289,7 +1317,7 @@ class User(Ruler):
|
|
|
1289
1317
|
if nexs:
|
|
1290
1318
|
await self.auth.setUserInfo(self.iden, 'roles', roles, mesg=mesg)
|
|
1291
1319
|
else:
|
|
1292
|
-
await self.auth.
|
|
1320
|
+
await self.auth._setUserInfo(self.iden, 'roles', roles, logged=nexs, mesg=mesg)
|
|
1293
1321
|
|
|
1294
1322
|
def isLocked(self):
|
|
1295
1323
|
return self.info.get('locked')
|
|
@@ -1332,7 +1360,7 @@ class User(Ruler):
|
|
|
1332
1360
|
if logged:
|
|
1333
1361
|
await self.auth.setUserInfo(self.iden, 'admin', admin, gateiden=gateiden)
|
|
1334
1362
|
else:
|
|
1335
|
-
await self.auth.
|
|
1363
|
+
await self.auth._setUserInfo(self.iden, 'admin', admin, gateiden=gateiden, logged=logged)
|
|
1336
1364
|
|
|
1337
1365
|
async def setLocked(self, locked, logged=True):
|
|
1338
1366
|
if not isinstance(locked, bool):
|
|
@@ -1352,9 +1380,9 @@ class User(Ruler):
|
|
|
1352
1380
|
await self.auth.setUserInfo(self.iden, 'policy:attempts', 0)
|
|
1353
1381
|
|
|
1354
1382
|
else:
|
|
1355
|
-
await self.auth.
|
|
1383
|
+
await self.auth._setUserInfo(self.iden, 'locked', locked, logged=logged)
|
|
1356
1384
|
if resetAttempts:
|
|
1357
|
-
await self.auth.
|
|
1385
|
+
await self.auth._setUserInfo(self.iden, 'policy:attempts', 0)
|
|
1358
1386
|
|
|
1359
1387
|
async def setArchived(self, archived):
|
|
1360
1388
|
if not isinstance(archived, bool):
|
|
@@ -1541,7 +1569,7 @@ class User(Ruler):
|
|
|
1541
1569
|
if nexs:
|
|
1542
1570
|
await self.auth.setUserInfo(self.iden, 'policy:previous', previous[:prevvalu])
|
|
1543
1571
|
else:
|
|
1544
|
-
await self.auth.
|
|
1572
|
+
await self.auth._setUserInfo(self.iden, 'policy:previous', previous[:prevvalu], logged=nexs)
|
|
1545
1573
|
|
|
1546
1574
|
async def setPasswd(self, passwd, nexs=True, enforce_policy=True):
|
|
1547
1575
|
# Prevent empty string or non-string values
|
|
@@ -1559,4 +1587,4 @@ class User(Ruler):
|
|
|
1559
1587
|
if nexs:
|
|
1560
1588
|
await self.auth.setUserInfo(self.iden, 'passwd', shadow)
|
|
1561
1589
|
else:
|
|
1562
|
-
await self.auth.
|
|
1590
|
+
await self.auth._setUserInfo(self.iden, 'passwd', shadow, logged=nexs)
|