synapse 2.178.0__py311-none-any.whl → 2.180.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.

Files changed (62) hide show
  1. synapse/cortex.py +166 -31
  2. synapse/datamodel.py +47 -1
  3. synapse/exc.py +1 -0
  4. synapse/lib/aha.py +2 -1
  5. synapse/lib/ast.py +110 -76
  6. synapse/lib/base.py +12 -3
  7. synapse/lib/cell.py +150 -11
  8. synapse/lib/coro.py +14 -0
  9. synapse/lib/drive.py +551 -0
  10. synapse/lib/layer.py +1 -1
  11. synapse/lib/lmdbslab.py +2 -0
  12. synapse/lib/modelrev.py +5 -1
  13. synapse/lib/node.py +14 -4
  14. synapse/lib/schemas.py +97 -0
  15. synapse/lib/snap.py +36 -11
  16. synapse/lib/storm.py +9 -5
  17. synapse/lib/stormhttp.py +1 -0
  18. synapse/lib/stormlib/modelext.py +29 -3
  19. synapse/lib/stormlib/stix.py +44 -17
  20. synapse/lib/stormlib/vault.py +2 -2
  21. synapse/lib/stormtypes.py +1 -1
  22. synapse/lib/types.py +9 -0
  23. synapse/lib/version.py +2 -2
  24. synapse/lookup/pe.py +303 -38
  25. synapse/models/auth.py +2 -0
  26. synapse/models/dns.py +24 -1
  27. synapse/models/geopol.py +3 -0
  28. synapse/models/geospace.py +4 -1
  29. synapse/models/inet.py +1 -0
  30. synapse/models/infotech.py +135 -92
  31. synapse/models/person.py +5 -2
  32. synapse/models/telco.py +3 -0
  33. synapse/tests/test_cortex.py +45 -1
  34. synapse/tests/test_lib_aha.py +17 -0
  35. synapse/tests/test_lib_ast.py +231 -0
  36. synapse/tests/test_lib_cell.py +225 -0
  37. synapse/tests/test_lib_coro.py +12 -0
  38. synapse/tests/test_lib_layer.py +22 -0
  39. synapse/tests/test_lib_modelrev.py +7 -0
  40. synapse/tests/test_lib_node.py +12 -1
  41. synapse/tests/test_lib_storm.py +32 -7
  42. synapse/tests/test_lib_stormhttp.py +40 -0
  43. synapse/tests/test_lib_stormlib_modelext.py +55 -3
  44. synapse/tests/test_lib_stormlib_stix.py +15 -0
  45. synapse/tests/test_lib_stormlib_vault.py +11 -1
  46. synapse/tests/test_lib_stormtypes.py +5 -0
  47. synapse/tests/test_lib_types.py +9 -0
  48. synapse/tests/test_model_dns.py +8 -0
  49. synapse/tests/test_model_geopol.py +2 -0
  50. synapse/tests/test_model_geospace.py +3 -1
  51. synapse/tests/test_model_inet.py +10 -1
  52. synapse/tests/test_model_infotech.py +47 -0
  53. synapse/tests/test_model_person.py +2 -0
  54. synapse/tests/test_model_syn.py +11 -0
  55. synapse/tests/test_model_telco.py +2 -1
  56. synapse/tests/test_utils_stormcov.py +1 -1
  57. synapse/tools/changelog.py +28 -0
  58. {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/METADATA +1 -1
  59. {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/RECORD +62 -61
  60. {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/WHEEL +1 -1
  61. {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/LICENSE +0 -0
  62. {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/top_level.txt +0 -0
synapse/cortex.py CHANGED
@@ -1354,20 +1354,20 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
1354
1354
  'desc': 'Controls access to adding specific extended model properties.',
1355
1355
  'ex': 'model.prop.add._foo:bar'},
1356
1356
  {'perm': ('model', 'prop', 'del'), 'gate': 'cortex',
1357
- 'desc': 'Controls access to deleting extended model properties.'},
1357
+ 'desc': 'Controls access to deleting extended model properties and values.'},
1358
1358
  {'perm': ('model', 'prop', 'del', '<form>'), 'gate': 'cortex',
1359
- 'desc': 'Controls access to deleting specific extended model properties.',
1359
+ 'desc': 'Controls access to deleting specific extended model properties and values.',
1360
1360
  'ex': 'model.prop.del._foo:bar'},
1361
1361
 
1362
1362
  {'perm': ('model', 'tagprop', 'add'), 'gate': 'cortex',
1363
- 'desc': 'Controls access to adding extended model tag properties.'},
1363
+ 'desc': 'Controls access to adding extended model tag properties and values.'},
1364
1364
  {'perm': ('model', 'tagprop', 'del'), 'gate': 'cortex',
1365
- 'desc': 'Controls access to deleting extended model tag properties.'},
1365
+ 'desc': 'Controls access to deleting extended model tag properties and values.'},
1366
1366
 
1367
1367
  {'perm': ('model', 'univ', 'add'), 'gate': 'cortex',
1368
1368
  'desc': 'Controls access to adding extended model universal properties.'},
1369
1369
  {'perm': ('model', 'univ', 'del'), 'gate': 'cortex',
1370
- 'desc': 'Controls access to deleting extended model universal properties.'},
1370
+ 'desc': 'Controls access to deleting extended model universal properties and values.'},
1371
1371
 
1372
1372
  {'perm': ('node',), 'gate': 'layer',
1373
1373
  'desc': 'Controls all node edits in a layer.'},
@@ -1626,6 +1626,25 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
1626
1626
  if self.isactive:
1627
1627
  await self.finiStormPool()
1628
1628
 
1629
+ @s_nexus.Pusher.onPushAuto('model:lock:prop')
1630
+ async def setPropLocked(self, name, locked):
1631
+ prop = self.model.reqProp(name)
1632
+ self.modellocks.set(f'prop/{name}', locked)
1633
+ prop.locked = locked
1634
+
1635
+ @s_nexus.Pusher.onPushAuto('model:lock:univ')
1636
+ async def setUnivLocked(self, name, locked):
1637
+ prop = self.model.reqUniv(name)
1638
+ self.modellocks.set(f'univ/{name}', locked)
1639
+ for prop in self.model.getAllUnivs(name):
1640
+ prop.locked = locked
1641
+
1642
+ @s_nexus.Pusher.onPushAuto('model:lock:tagprop')
1643
+ async def setTagPropLocked(self, name, locked):
1644
+ prop = self.model.reqTagProp(name)
1645
+ self.modellocks.set(f'tagprop/{name}', locked)
1646
+ prop.locked = locked
1647
+
1629
1648
  @s_nexus.Pusher.onPushAuto('model:depr:lock')
1630
1649
  async def setDeprLock(self, name, locked):
1631
1650
 
@@ -2093,17 +2112,15 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
2093
2112
  async def onSetTrigDoc(node, prop, valu):
2094
2113
  valu = str(valu)
2095
2114
  iden = node.ndef[1]
2096
- trig = node.snap.view.triggers.get(iden)
2097
2115
  node.snap.user.confirm(('trigger', 'set', 'doc'), gateiden=iden)
2098
- await trig.set('doc', valu)
2116
+ await node.snap.view.setTriggerInfo(iden, 'doc', valu)
2099
2117
  node.props[prop.name] = valu
2100
2118
 
2101
2119
  async def onSetTrigName(node, prop, valu):
2102
2120
  valu = str(valu)
2103
2121
  iden = node.ndef[1]
2104
- trig = node.snap.view.triggers.get(iden)
2105
2122
  node.snap.user.confirm(('trigger', 'set', 'name'), gateiden=iden)
2106
- await trig.set('name', valu)
2123
+ await node.snap.view.setTriggerInfo(iden, 'name', valu)
2107
2124
  node.props[prop.name] = valu
2108
2125
 
2109
2126
  async def onSetCronDoc(node, prop, valu):
@@ -3437,7 +3454,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3437
3454
 
3438
3455
  for layr in self.layers.values():
3439
3456
  async for item in layr.iterFormRows(formname):
3440
- mesg = f'Nodes still exist with form: {formname}'
3457
+ mesg = f'Nodes still exist with form: {formname} in layer {layr.iden}'
3441
3458
  raise s_exc.CantDelForm(mesg=mesg)
3442
3459
 
3443
3460
  self.model.delForm(formname)
@@ -3486,14 +3503,116 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3486
3503
  await self.feedBeholder('model:prop:add', {'form': form, 'prop': prop.pack()})
3487
3504
 
3488
3505
  async def delFormProp(self, form, prop):
3506
+ self.reqExtProp(form, prop)
3507
+ return await self._push('model:prop:del', form, prop)
3508
+
3509
+ async def _delAllFormProp(self, formname, propname, meta):
3510
+ '''
3511
+ Delete all instances of a property from all layers.
3512
+
3513
+ NOTE: This does not fire triggers.
3514
+ '''
3515
+ self.reqExtProp(formname, propname)
3516
+
3517
+ fullname = f'{formname}:{propname}'
3518
+ prop = self.model.prop(fullname)
3519
+
3520
+ await self.setPropLocked(fullname, True)
3521
+
3522
+ for layr in list(self.layers.values()):
3523
+
3524
+ genr = layr.iterPropRows(formname, propname)
3525
+
3526
+ async for rows in s_coro.chunks(genr):
3527
+ nodeedits = []
3528
+ for buid, valu in rows:
3529
+ nodeedits.append((buid, prop.form.name, (
3530
+ (s_layer.EDIT_PROP_DEL, (prop.name, None, prop.type.stortype), ()),
3531
+ )))
3532
+
3533
+ await layr.saveNodeEdits(nodeedits, meta)
3534
+ await asyncio.sleep(0)
3535
+
3536
+ async def _delAllUnivProp(self, propname, meta):
3537
+ '''
3538
+ Delete all instances of a universal property from all layers.
3539
+
3540
+ NOTE: This does not fire triggers.
3541
+ '''
3542
+ self.reqExtUniv(propname)
3543
+
3544
+ full = f'.{propname}'
3545
+ prop = self.model.univ(full)
3546
+
3547
+ await self.setUnivLocked(full, True)
3548
+
3549
+ for layr in list(self.layers.values()):
3550
+
3551
+ genr = layr.iterUnivRows(full)
3552
+
3553
+ async for rows in s_coro.chunks(genr):
3554
+ nodeedits = []
3555
+ for buid, valu in rows:
3556
+ sode = await layr.getStorNode(buid)
3557
+ nodeedits.append((buid, sode.get('form'), (
3558
+ (s_layer.EDIT_PROP_DEL, (prop.name, None, prop.type.stortype), ()),
3559
+ )))
3560
+
3561
+ await layr.saveNodeEdits(nodeedits, meta)
3562
+ await asyncio.sleep(0)
3563
+
3564
+ async def _delAllTagProp(self, propname, meta):
3565
+ '''
3566
+ Delete all instances of a tag property from all layers.
3567
+
3568
+ NOTE: This does not fire triggers.
3569
+ '''
3570
+ self.reqExtTagProp(propname)
3571
+ prop = self.model.getTagProp(propname)
3572
+
3573
+ await self.setTagPropLocked(propname, True)
3574
+
3575
+ for layr in list(self.layers.values()):
3576
+
3577
+ for form, tag, tagprop in layr.getTagProps():
3578
+
3579
+ if tagprop != propname: # pragma: no cover
3580
+ await asyncio.sleep(0)
3581
+ continue
3582
+
3583
+ genr = layr.iterTagPropRows(tag, tagprop, form)
3584
+
3585
+ async for rows in s_coro.chunks(genr):
3586
+ nodeedits = []
3587
+ for buid, valu in rows:
3588
+ nodeedits.append((buid, form, (
3589
+ (s_layer.EDIT_TAGPROP_DEL, (tag, prop.name, None, prop.type.stortype), ()),
3590
+ )))
3591
+
3592
+ await layr.saveNodeEdits(nodeedits, meta)
3593
+ await asyncio.sleep(0)
3594
+
3595
+ def reqExtProp(self, form, prop):
3489
3596
  full = f'{form}:{prop}'
3490
3597
  pdef = self.extprops.get(full)
3491
-
3492
3598
  if pdef is None:
3493
3599
  mesg = f'No ext prop named {full}'
3494
3600
  raise s_exc.NoSuchProp(form=form, prop=prop, mesg=mesg)
3601
+ return pdef
3495
3602
 
3496
- return await self._push('model:prop:del', form, prop)
3603
+ def reqExtUniv(self, prop):
3604
+ udef = self.extunivs.get(prop)
3605
+ if udef is None:
3606
+ mesg = f'No ext univ named {prop}'
3607
+ raise s_exc.NoSuchUniv(name=prop, mesg=mesg)
3608
+ return udef
3609
+
3610
+ def reqExtTagProp(self, name):
3611
+ pdef = self.exttagprops.get(name)
3612
+ if pdef is None:
3613
+ mesg = f'No tag prop named {name}'
3614
+ raise s_exc.NoSuchTagProp(mesg=mesg, name=name)
3615
+ return pdef
3497
3616
 
3498
3617
  @s_nexus.Pusher.onPush('model:prop:del')
3499
3618
  async def _delFormProp(self, form, prop):
@@ -3508,22 +3627,19 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3508
3627
 
3509
3628
  for layr in self.layers.values():
3510
3629
  async for item in layr.iterPropRows(form, prop):
3511
- mesg = f'Nodes still exist with prop: {form}:{prop}'
3630
+ mesg = f'Nodes still exist with prop: {form}:{prop} in layer {layr.iden}'
3512
3631
  raise s_exc.CantDelProp(mesg=mesg)
3513
3632
 
3514
3633
  self.model.delFormProp(form, prop)
3515
3634
  self.extprops.pop(full, None)
3635
+ self.modellocks.pop(f'prop/{full}', None)
3516
3636
  await self.fire('core:extmodel:change',
3517
3637
  form=form, prop=prop, act='del', type='formprop')
3518
3638
 
3519
3639
  await self.feedBeholder('model:prop:del', {'form': form, 'prop': prop})
3520
3640
 
3521
3641
  async def delUnivProp(self, prop):
3522
- udef = self.extunivs.get(prop)
3523
- if udef is None:
3524
- mesg = f'No ext univ named {prop}'
3525
- raise s_exc.NoSuchUniv(name=prop, mesg=mesg)
3526
-
3642
+ self.reqExtUniv(prop)
3527
3643
  return await self._push('model:univ:del', prop)
3528
3644
 
3529
3645
  @s_nexus.Pusher.onPush('model:univ:del')
@@ -3538,11 +3654,12 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3538
3654
  univname = '.' + prop
3539
3655
  for layr in self.layers.values():
3540
3656
  async for item in layr.iterUnivRows(univname):
3541
- mesg = f'Nodes still exist with universal prop: {prop}'
3657
+ mesg = f'Nodes still exist with universal prop: {prop} in layer {layr.iden}'
3542
3658
  raise s_exc.CantDelUniv(mesg=mesg)
3543
3659
 
3544
3660
  self.model.delUnivProp(prop)
3545
3661
  self.extunivs.pop(prop, None)
3662
+ self.modellocks.pop(f'univ/{prop}', None)
3546
3663
  await self.fire('core:extmodel:change', name=prop, act='del', type='univ')
3547
3664
  await self.feedBeholder('model:univ:del', {'prop': univname})
3548
3665
 
@@ -3574,11 +3691,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3574
3691
  await self.feedBeholder('model:tagprop:add', tagp.pack())
3575
3692
 
3576
3693
  async def delTagProp(self, name):
3577
- pdef = self.exttagprops.get(name)
3578
- if pdef is None:
3579
- mesg = f'No tag prop named {name}'
3580
- raise s_exc.NoSuchProp(mesg=mesg, name=name)
3581
-
3694
+ self.reqExtTagProp(name)
3582
3695
  return await self._push('model:tagprop:del', name)
3583
3696
 
3584
3697
  @s_nexus.Pusher.onPush('model:tagprop:del')
@@ -3589,12 +3702,13 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3589
3702
 
3590
3703
  for layr in self.layers.values():
3591
3704
  if await layr.hasTagProp(name):
3592
- mesg = f'Nodes still exist with tagprop: {name}'
3705
+ mesg = f'Nodes still exist with tagprop: {name} in layer {layr.iden}'
3593
3706
  raise s_exc.CantDelProp(mesg=mesg)
3594
3707
 
3595
3708
  self.model.delTagProp(name)
3596
3709
 
3597
3710
  self.exttagprops.pop(name, None)
3711
+ self.modellocks.pop(f'tagprop/{name}', None)
3598
3712
  await self.fire('core:tagprop:change', name=name, act='del')
3599
3713
  await self.feedBeholder('model:tagprop:del', {'tagprop': name})
3600
3714
 
@@ -3941,7 +4055,10 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3941
4055
  self.stormvars.set(s_stormlib_cell.runtime_fixes_key, s_stormlib_cell.getMaxHotFixes())
3942
4056
 
3943
4057
  async def _initDeprLocks(self):
4058
+
3944
4059
  self.deprlocks = self.cortexdata.getSubKeyVal('model:deprlocks:')
4060
+ self.modellocks = self.cortexdata.getSubKeyVal('model:locks:')
4061
+
3945
4062
  # TODO: 3.0.0 conversion will truncate this hive key
3946
4063
 
3947
4064
  if self.inaugural:
@@ -3967,6 +4084,24 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3967
4084
  if _type is not None:
3968
4085
  _type.locked = locked
3969
4086
 
4087
+ for name, locked in self.modellocks.items():
4088
+
4089
+ prop = None
4090
+ elemtype, elemname = name.split('/', 1)
4091
+
4092
+ if elemtype == 'prop':
4093
+ prop = self.model.prop(elemname)
4094
+ elif elemtype == 'univ':
4095
+ prop = self.model.univ(elemname)
4096
+ if prop is not None:
4097
+ for univ in self.model.getAllUnivs(elemname):
4098
+ univ.locked = locked
4099
+ elif elemtype == 'tagprop':
4100
+ prop = self.model.getTagProp(elemname)
4101
+
4102
+ if prop is not None:
4103
+ prop.locked = locked
4104
+
3970
4105
  async def _initJsonStor(self):
3971
4106
 
3972
4107
  self.jsonurl = self.conf.get('jsonstor')
@@ -5595,7 +5730,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
5595
5730
 
5596
5731
  if (nexsoffs := opts.get('nexsoffs')) is not None:
5597
5732
  if not await self.waitNexsOffs(nexsoffs, timeout=opts.get('nexstimeout')):
5598
- raise s_exc.TimeOut(mesg=f'Timeout waiting for nexus offset {nexsoffs}.')
5733
+ raise s_exc.TimeOut(mesg=f'Timeout waiting for nexus offset {nexsoffs} in count()')
5599
5734
 
5600
5735
  view = self._viewFromOpts(opts)
5601
5736
 
@@ -5659,7 +5794,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
5659
5794
 
5660
5795
  if (nexsoffs := opts.get('nexsoffs')) is not None:
5661
5796
  if not await self.waitNexsOffs(nexsoffs, timeout=opts.get('nexstimeout')):
5662
- raise s_exc.TimeOut(mesg=f'Timeout waiting for nexus offset {nexsoffs}.')
5797
+ raise s_exc.TimeOut(mesg=f'Timeout waiting for nexus offset {nexsoffs} in storm().')
5663
5798
 
5664
5799
  view = self._viewFromOpts(opts)
5665
5800
  async for mesg in view.storm(text, opts=opts):
@@ -5686,7 +5821,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
5686
5821
 
5687
5822
  if (nexsoffs := opts.get('nexsoffs')) is not None:
5688
5823
  if not await self.waitNexsOffs(nexsoffs, timeout=opts.get('nexstimeout')):
5689
- raise s_exc.TimeOut(mesg=f'Timeout waiting for nexus offset {nexsoffs}.')
5824
+ raise s_exc.TimeOut(mesg=f'Timeout waiting for nexus offset {nexsoffs} in callStorm().')
5690
5825
 
5691
5826
  view = self._viewFromOpts(opts)
5692
5827
  return await view.callStorm(text, opts=opts)
@@ -5714,7 +5849,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
5714
5849
 
5715
5850
  if (nexsoffs := opts.get('nexsoffs')) is not None:
5716
5851
  if not await self.waitNexsOffs(nexsoffs, timeout=opts.get('nexstimeout')):
5717
- raise s_exc.TimeOut(mesg=f'Timeout waiting for nexus offset {nexsoffs}.')
5852
+ raise s_exc.TimeOut(mesg=f'Timeout waiting for nexus offset {nexsoffs} in exportStorm().')
5718
5853
 
5719
5854
  user = self._userFromOpts(opts)
5720
5855
  view = self._viewFromOpts(opts)
@@ -7072,6 +7207,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
7072
7207
  raise s_exc.BadArg('Only vault names and permissions can be changed.')
7073
7208
 
7074
7209
  vault = self.reqVault(iden)
7210
+ oldv = vault.get(key)
7075
7211
  vault[key] = valu
7076
7212
 
7077
7213
  s_schemas.reqValidVault(vault)
@@ -7079,8 +7215,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
7079
7215
  bidn = s_common.uhex(iden)
7080
7216
 
7081
7217
  if key == 'name':
7082
- name = vault.get('name')
7083
- self.slab.delete(name.encode(), db=self.vaultsbynamedb)
7218
+ self.slab.delete(oldv.encode(), db=self.vaultsbynamedb)
7084
7219
  self.slab.put(valu.encode(), bidn, db=self.vaultsbynamedb)
7085
7220
 
7086
7221
  self.slab.put(bidn, s_msgpack.en(vault), db=self.vaultsdb)
synapse/datamodel.py CHANGED
@@ -30,6 +30,7 @@ class TagProp:
30
30
  self.info = info
31
31
  self.tdef = tdef
32
32
  self.model = model
33
+ self.locked = False
33
34
 
34
35
  self.utf8 = name.encode()
35
36
  self.nenc = name.encode() + b'\x00'
@@ -127,6 +128,10 @@ class Prop:
127
128
  self.deprecated = self.info.get('deprecated', False)
128
129
 
129
130
  self.type = self.modl.getTypeClone(typedef)
131
+ self.typehash = self.type.typehash
132
+
133
+ if self.type.isarray:
134
+ self.arraytypehash = self.type.arraytype.typehash
130
135
 
131
136
  if form is not None:
132
137
  form.setProp(name, self)
@@ -269,6 +274,11 @@ class Form:
269
274
  if self.type is None:
270
275
  raise s_exc.NoSuchType(name=name)
271
276
 
277
+ self.typehash = self.type.typehash
278
+
279
+ if self.type.isarray:
280
+ self.arraytypehash = self.type.arraytype.typehash
281
+
272
282
  self.form = self
273
283
 
274
284
  self.props = {} # name: Prop()
@@ -462,6 +472,7 @@ class Model:
462
472
  self.modeldefs = []
463
473
 
464
474
  self.univs = {}
475
+ self.allunivs = collections.defaultdict(list)
465
476
 
466
477
  self.propsbytype = collections.defaultdict(dict) # name: Prop()
467
478
  self.arraysbytype = collections.defaultdict(dict)
@@ -620,6 +631,30 @@ class Model:
620
631
  self.formprefixcache[prefix] = forms
621
632
  return forms
622
633
 
634
+ def reqProp(self, name):
635
+ prop = self.prop(name)
636
+ if prop is not None:
637
+ return prop
638
+
639
+ mesg = f'No property named {name}.'
640
+ raise s_exc.NoSuchProp(mesg=mesg, name=name)
641
+
642
+ def reqUniv(self, name):
643
+ prop = self.univ(name)
644
+ if prop is not None:
645
+ return prop
646
+
647
+ mesg = f'No universal property named {name}.'
648
+ raise s_exc.NoSuchUniv(mesg=mesg, name=name)
649
+
650
+ def reqTagProp(self, name):
651
+ prop = self.getTagProp(name)
652
+ if prop is not None:
653
+ return prop
654
+
655
+ mesg = f'No tag property named {name}.'
656
+ raise s_exc.NoSuchTagProp(mesg=mesg, name=name)
657
+
623
658
  def reqFormsByPrefix(self, prefix, extra=None):
624
659
  forms = self.getFormsByPrefix(prefix)
625
660
  if not forms:
@@ -965,13 +1000,18 @@ class Model:
965
1000
 
966
1001
  def _addFormUniv(self, form, name, tdef, info):
967
1002
 
1003
+ univ = self.reqUniv(name)
1004
+
968
1005
  prop = Prop(self, form, name, tdef, info)
1006
+ prop.locked = univ.locked
969
1007
 
970
1008
  full = f'{form.name}{name}'
971
1009
 
972
1010
  self.props[full] = prop
973
1011
  self.props[(form.name, name)] = prop
974
1012
 
1013
+ self.allunivs[name].append(prop)
1014
+
975
1015
  def addUnivProp(self, name, tdef, info):
976
1016
 
977
1017
  base = '.' + name
@@ -985,8 +1025,13 @@ class Model:
985
1025
  self.props[base] = univ
986
1026
  self.univs[base] = univ
987
1027
 
1028
+ self.allunivs[base].append(univ)
1029
+
988
1030
  for form in self.forms.values():
989
- self._addFormUniv(form, base, tdef, info)
1031
+ prop = self._addFormUniv(form, base, tdef, info)
1032
+
1033
+ def getAllUnivs(self, name):
1034
+ return list(self.allunivs.get(name, ()))
990
1035
 
991
1036
  def addFormProp(self, formname, propname, tdef, info):
992
1037
  form = self.forms.get(formname)
@@ -1090,6 +1135,7 @@ class Model:
1090
1135
  raise s_exc.NoSuchUniv(name=propname)
1091
1136
 
1092
1137
  self.univs.pop(univname, None)
1138
+ self.allunivs.pop(univname, None)
1093
1139
 
1094
1140
  for form in self.forms.values():
1095
1141
  self.delFormProp(form.name, univname)
synapse/exc.py CHANGED
@@ -77,6 +77,7 @@ class BackupAlreadyRunning(SynErr):
77
77
  class StormPkgRequires(SynErr): pass
78
78
  class StormPkgConflicts(SynErr): pass
79
79
 
80
+ class BadName(SynErr): pass
80
81
  class BadPkgDef(SynErr): pass
81
82
  class BadCmdName(SynErr): pass
82
83
  class BadCmprValu(SynErr): pass
synapse/lib/aha.py CHANGED
@@ -733,7 +733,7 @@ class AhaCell(s_cell.Cell):
733
733
  # that do not intend to listen for provisioning.
734
734
  hostname = self.conf.get('dns:name')
735
735
  if hostname is not None:
736
- return f'ssl://{hostname}:27272'
736
+ return f'ssl://0.0.0.0:27272?hostname={hostname}'
737
737
 
738
738
  def _getDmonListen(self):
739
739
 
@@ -776,6 +776,7 @@ class AhaCell(s_cell.Cell):
776
776
  if provurl is not None:
777
777
  self.provdmon = await ProvDmon.anit(self)
778
778
  self.onfini(self.provdmon)
779
+ logger.info(f'provision listening: {provurl}')
779
780
  self.provaddr = await self.provdmon.listen(provurl)
780
781
 
781
782
  async def _clearInactiveSessions(self):