synapse 2.222.0__py311-none-any.whl → 2.223.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.

@@ -0,0 +1,115 @@
1
+ import asyncio
2
+ import logging
3
+
4
+ import synapse.exc as s_exc
5
+ import synapse.lib.stormtypes as s_stormtypes
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ stormcmds = [
10
+ {
11
+ 'name': 'task.list',
12
+ 'descr': 'List running tasks on the Cortex and any mirrors.',
13
+ 'cmdargs': (
14
+ ('--verbose', {'default': False, 'action': 'store_true', 'help': 'Enable verbose output.'}),
15
+ ),
16
+ 'storm': '''
17
+ $tcnt = (0)
18
+ for $task in $lib.task.list() {
19
+ $lib.print(`task iden: {$task.iden}`)
20
+ $lib.print(` name: {$task.name}`)
21
+ $lib.print(` user: {$task.username}`)
22
+ $lib.print(` service: {$task.service}`)
23
+ $lib.print(` start time: {$lib.time.format($task.tick, '%Y-%m-%d %H:%M:%S')}`)
24
+ $lib.print(' metadata:')
25
+ if $cmdopts.verbose {
26
+ $lib.pprint($task.info, prefix=' ')
27
+ } else {
28
+ $lib.pprint($task.info, prefix=' ', clamp=120)
29
+ }
30
+ $tcnt = ($tcnt + 1)
31
+ }
32
+
33
+ if ($tcnt = 1) {
34
+ $lib.print('1 task found.')
35
+ } else {
36
+ $lib.print(`{$tcnt} tasks found.`)
37
+ }
38
+ ''',
39
+ },
40
+ {
41
+ 'name': 'task.kill',
42
+ 'descr': 'Kill a running task on the Cortex or a mirror.',
43
+ 'cmdargs': (
44
+ ('iden', {'help': 'Any prefix that matches exactly one valid task iden is accepted.'}),
45
+ ),
46
+ 'storm': '''
47
+ $kild = $lib.task.kill($cmdopts.iden)
48
+ $lib.print("kill status: {kild}", kild=$kild)
49
+ ''',
50
+ },
51
+ ]
52
+
53
+ @s_stormtypes.registry.registerLib
54
+ class LibTask(s_stormtypes.Lib):
55
+ '''
56
+ A Storm Library for interacting with tasks on a Cortex and its mirrors.
57
+ '''
58
+ _storm_locals = (
59
+ {'name': 'list', 'desc': 'List tasks the current user can access on the Cortex and its mirrors.',
60
+ 'type': {'type': 'function', '_funcname': '_methTaskList', 'args': (),
61
+ 'returns': {'name': 'yields', 'type': 'dict', 'desc': 'Task definitions.'}}},
62
+ {'name': 'kill', 'desc': 'Stop a running task on the Cortex or a mirror.',
63
+ 'type': {'type': 'function', '_funcname': '_methTaskKill', 'args': (
64
+ {'name': 'prefix', 'type': 'str',
65
+ 'desc': 'The prefix of the task to stop. '
66
+ 'Tasks will only be stopped if there is a single prefix match.'},),
67
+ 'returns': {'type': 'boolean', 'desc': 'True if the task was cancelled, False otherwise.'}}},
68
+ )
69
+ _storm_lib_path = ('task',)
70
+ _storm_lib_perms = (
71
+ {'perm': ('task', 'get'), 'gate': 'cortex',
72
+ 'desc': 'Permits a user to view tasks owned by other users.'},
73
+ {'perm': ('task', 'del'), 'gate': 'cortex',
74
+ 'desc': 'Permits a user to kill tasks owned by other users.'},
75
+ )
76
+
77
+ def getObjLocals(self):
78
+ return {
79
+ 'list': self._methTaskList,
80
+ 'kill': self._methTaskKill,
81
+ }
82
+
83
+ @s_stormtypes.stormfunc(readonly=True)
84
+ async def _methTaskList(self):
85
+ useriden = self.runt.user.iden
86
+ isallowed = self.runt.allowed(('task', 'get'))
87
+
88
+ async for task in self.runt.snap.core.getTasks():
89
+ if isallowed or task['user'] == useriden:
90
+ yield task
91
+
92
+ async def _methTaskKill(self, prefix):
93
+ useriden = self.runt.user.iden
94
+ isallowed = self.runt.allowed(('task', 'del'))
95
+
96
+ prefix = await s_stormtypes.tostr(prefix)
97
+ if not prefix:
98
+ mesg = 'An empty task iden prefix is not allowed.'
99
+ raise s_exc.StormRuntimeError(mesg=mesg, iden=prefix)
100
+
101
+ iden = None
102
+ async for task in self.runt.snap.core.getTasks():
103
+ taskiden = task['iden']
104
+ if (isallowed or task['user'] == useriden) and taskiden.startswith(prefix):
105
+ if iden is None:
106
+ iden = taskiden
107
+ else:
108
+ mesg = 'Provided iden matches more than one task.'
109
+ raise s_exc.StormRuntimeError(mesg=mesg, iden=prefix)
110
+
111
+ if iden is None:
112
+ mesg = 'Provided iden does not match any tasks.'
113
+ raise s_exc.StormRuntimeError(mesg=mesg, iden=prefix)
114
+
115
+ return await self.runt.snap.core.killTask(iden)
synapse/lib/stormtypes.py CHANGED
@@ -699,117 +699,6 @@ class Lib(StormType):
699
699
  async for item in self.runt.dyniter(iden, todo, gatekeys=gatekeys):
700
700
  yield item
701
701
 
702
- @registry.registerLib
703
- class LibPkg(Lib):
704
- '''
705
- A Storm Library for interacting with Storm Packages.
706
- '''
707
- _storm_locals = (
708
- {'name': 'add', 'desc': 'Add a Storm Package to the Cortex.',
709
- 'type': {'type': 'function', '_funcname': '_libPkgAdd',
710
- 'args': (
711
- {'name': 'pkgdef', 'type': 'dict', 'desc': 'A Storm Package definition.', },
712
- {'name': 'verify', 'type': 'boolean', 'default': False,
713
- 'desc': 'Verify storm package signature.', },
714
- ),
715
- 'returns': {'type': 'null', }}},
716
- {'name': 'get', 'desc': 'Get a Storm Package from the Cortex.',
717
- 'type': {'type': 'function', '_funcname': '_libPkgGet',
718
- 'args': (
719
- {'name': 'name', 'type': 'str', 'desc': 'A Storm Package name.', },
720
- ),
721
- 'returns': {'type': 'dict', 'desc': 'The Storm package definition.', }}},
722
- {'name': 'has', 'desc': 'Check if a Storm Package is available in the Cortex.',
723
- 'type': {'type': 'function', '_funcname': '_libPkgHas',
724
- 'args': (
725
- {'name': 'name', 'type': 'str',
726
- 'desc': 'A Storm Package name to check for the existence of.', },
727
- ),
728
- 'returns': {'type': 'boolean',
729
- 'desc': 'True if the package exists in the Cortex, False if it does not.', }}},
730
- {'name': 'del', 'desc': 'Delete a Storm Package from the Cortex.',
731
- 'type': {'type': 'function', '_funcname': '_libPkgDel',
732
- 'args': (
733
- {'name': 'name', 'type': 'str', 'desc': 'The name of the package to delete.', },
734
- ),
735
- 'returns': {'type': 'null', }}},
736
- {'name': 'list', 'desc': 'Get a list of Storm Packages loaded in the Cortex.',
737
- 'type': {'type': 'function', '_funcname': '_libPkgList',
738
- 'returns': {'type': 'list', 'desc': 'A list of Storm Package definitions.', }}},
739
- {'name': 'deps', 'desc': 'Verify the dependencies for a Storm Package.',
740
- 'type': {'type': 'function', '_funcname': '_libPkgDeps',
741
- 'args': (
742
- {'name': 'pkgdef', 'type': 'dict', 'desc': 'A Storm Package definition.', },
743
- ),
744
- 'returns': {'type': 'dict', 'desc': 'A dictionary listing dependencies and if they are met.', }}},
745
- {'name': 'vars',
746
- 'desc': "Get a dictionary representing the package's persistent variables.",
747
- 'type': {'type': 'function', '_funcname': '_libPkgVars',
748
- 'args': (
749
- {'name': 'name', 'type': 'str',
750
- 'desc': 'A Storm Package name to get vars for.', },
751
- ),
752
- 'returns': {'type': 'pkg:vars', 'desc': 'A dictionary representing the package variables.', }}},
753
- )
754
- _storm_lib_perms = (
755
- {'perm': ('power-ups', '<name>', 'admin'), 'gate': 'cortex',
756
- 'desc': 'Controls the ability to interact with the vars for a Storm Package by name.'},
757
- )
758
- _storm_lib_path = ('pkg',)
759
-
760
- def getObjLocals(self):
761
- return {
762
- 'add': self._libPkgAdd,
763
- 'get': self._libPkgGet,
764
- 'has': self._libPkgHas,
765
- 'del': self._libPkgDel,
766
- 'list': self._libPkgList,
767
- 'deps': self._libPkgDeps,
768
- 'vars': self._libPkgVars,
769
- }
770
-
771
- async def _libPkgAdd(self, pkgdef, verify=False):
772
- self.runt.confirm(('pkg', 'add'), None)
773
- pkgdef = await toprim(pkgdef)
774
- verify = await tobool(verify)
775
- await self.runt.snap.core.addStormPkg(pkgdef, verify=verify)
776
-
777
- @stormfunc(readonly=True)
778
- async def _libPkgGet(self, name):
779
- name = await tostr(name)
780
- pkgdef = await self.runt.snap.core.getStormPkg(name)
781
- if pkgdef is None:
782
- return None
783
-
784
- return Dict(pkgdef)
785
-
786
- @stormfunc(readonly=True)
787
- async def _libPkgHas(self, name):
788
- name = await tostr(name)
789
- pkgdef = await self.runt.snap.core.getStormPkg(name)
790
- if pkgdef is None:
791
- return False
792
- return True
793
-
794
- async def _libPkgDel(self, name):
795
- self.runt.confirm(('pkg', 'del'), None)
796
- await self.runt.snap.core.delStormPkg(name)
797
-
798
- @stormfunc(readonly=True)
799
- async def _libPkgList(self):
800
- pkgs = await self.runt.snap.core.getStormPkgs()
801
- return list(sorted(pkgs, key=lambda x: x.get('name')))
802
-
803
- @stormfunc(readonly=True)
804
- async def _libPkgDeps(self, pkgdef):
805
- pkgdef = await toprim(pkgdef)
806
- return await self.runt.snap.core.verifyStormPkgDeps(pkgdef)
807
-
808
- async def _libPkgVars(self, name):
809
- name = await tostr(name)
810
- confirm(('power-ups', name, 'admin'))
811
- return PkgVars(self.runt, name)
812
-
813
702
  @registry.registerLib
814
703
  class LibDmon(Lib):
815
704
  '''
@@ -3956,22 +3845,22 @@ class LibQueue(Lib):
3956
3845
  {'name': 'add', 'desc': 'Add a Queue to the Cortex with a given name.',
3957
3846
  'type': {'type': 'function', '_funcname': '_methQueueAdd',
3958
3847
  'args': (
3959
- {'name': 'name', 'type': 'str', 'desc': 'The name of the queue to add.', },
3848
+ {'name': 'name', 'type': 'str', 'desc': 'The name of the Queue to add.', },
3960
3849
  ),
3961
3850
  'returns': {'type': 'queue', }}},
3962
- {'name': 'gen', 'desc': 'Add or get a Storm Queue in a single operation.',
3851
+ {'name': 'gen', 'desc': 'Add or get a Queue in a single operation.',
3963
3852
  'type': {'type': 'function', '_funcname': '_methQueueGen',
3964
3853
  'args': (
3965
3854
  {'name': 'name', 'type': 'str', 'desc': 'The name of the Queue to add or get.', },
3966
3855
  ),
3967
3856
  'returns': {'type': 'queue', }}},
3968
- {'name': 'del', 'desc': 'Delete a given named Queue.',
3857
+ {'name': 'del', 'desc': 'Delete a given Queue.',
3969
3858
  'type': {'type': 'function', '_funcname': '_methQueueDel',
3970
3859
  'args': (
3971
- {'name': 'name', 'type': 'str', 'desc': 'The name of the queue to delete.', },
3860
+ {'name': 'name', 'type': 'str', 'desc': 'The name of the Queue to delete.', },
3972
3861
  ),
3973
3862
  'returns': {'type': 'null', }}},
3974
- {'name': 'get', 'desc': 'Get an existing Storm Queue object.',
3863
+ {'name': 'get', 'desc': 'Get an existing Queue.',
3975
3864
  'type': {'type': 'function', '_funcname': '_methQueueGet',
3976
3865
  'args': (
3977
3866
  {'name': 'name', 'type': 'str', 'desc': 'The name of the Queue to get.', },
@@ -3980,17 +3869,17 @@ class LibQueue(Lib):
3980
3869
  {'name': 'list', 'desc': 'Get a list of the Queues in the Cortex.',
3981
3870
  'type': {'type': 'function', '_funcname': '_methQueueList',
3982
3871
  'returns': {'type': 'list',
3983
- 'desc': 'A list of queue definitions the current user is allowed to interact with.', }}},
3872
+ 'desc': 'A list of Queue definitions the current user is allowed to interact with.', }}},
3984
3873
  )
3985
3874
  _storm_lib_perms = (
3986
3875
  {'perm': ('queue', 'add'), 'gate': 'cortex',
3987
- 'desc': 'Permits a user to create a named queue.'},
3876
+ 'desc': 'Permits a user to create a Queue.'},
3988
3877
  {'perm': ('queue', 'get'), 'gate': 'queue',
3989
- 'desc': 'Permits a user to access a queue. This allows the user to read from the queue and remove items from it.'},
3878
+ 'desc': 'Permits a user to access a Queue. This allows the user to read from the Queue and remove items from it.'},
3990
3879
  {'perm': ('queue', 'put'), 'gate': 'queue',
3991
- 'desc': 'Permits a user to put items into a queue.'},
3880
+ 'desc': 'Permits a user to put items into a Queue.'},
3992
3881
  {'perm': ('queue', 'del'), 'gate': 'queue',
3993
- 'desc': 'Permits a user to delete a queue.'},
3882
+ 'desc': 'Permits a user to delete a Queue.'},
3994
3883
  )
3995
3884
  _storm_lib_path = ('queue',)
3996
3885
 
@@ -4053,7 +3942,7 @@ class LibQueue(Lib):
4053
3942
  @registry.registerType
4054
3943
  class Queue(StormType):
4055
3944
  '''
4056
- A StormLib API instance of a named channel in the Cortex multiqueue.
3945
+ A StormLib API instance of a named channel in the Cortex MultiQueue.
4057
3946
  '''
4058
3947
  _storm_locals = (
4059
3948
  {'name': 'name', 'desc': 'The name of the Queue.', 'type': 'str', },
@@ -4067,48 +3956,48 @@ class Queue(StormType):
4067
3956
  'desc': 'Wait for the offset to be available before returning the item.', },
4068
3957
  ),
4069
3958
  'returns': {'type': 'list',
4070
- 'desc': 'A tuple of the offset and the item from the queue. If wait is false and '
3959
+ 'desc': 'A tuple of the offset and the item from the Queue. If wait is false and '
4071
3960
  'the offset is not present, null is returned.', }}},
4072
- {'name': 'pop', 'desc': 'Pop a item from the Queue at a specific offset.',
3961
+ {'name': 'pop', 'desc': 'Pop an item from the Queue at a specific offset.',
4073
3962
  'type': {'type': 'function', '_funcname': '_methQueuePop',
4074
3963
  'args': (
4075
3964
  {'name': 'offs', 'type': 'int', 'default': None,
4076
- 'desc': 'Offset to pop the item from. If not specified, the first item in the queue will be'
3965
+ 'desc': 'Offset to pop the item from. If not specified, the first item in the Queue will be'
4077
3966
  ' popped.', },
4078
3967
  {'name': 'wait', 'type': 'boolean', 'default': False,
4079
3968
  'desc': 'Wait for an item to be available to pop.'},
4080
3969
  ),
4081
3970
  'returns': {'type': 'list',
4082
- 'desc': 'The offset and item popped from the queue. If there is no item at the '
4083
- 'offset or the queue is empty and wait is false, it returns null.', }}},
4084
- {'name': 'put', 'desc': 'Put an item into the queue.',
3971
+ 'desc': 'The offset and item popped from the Queue. If there is no item at the '
3972
+ 'offset or the Queue is empty and wait is false, it returns null.', }}},
3973
+ {'name': 'put', 'desc': 'Put an item into the Queue.',
4085
3974
  'type': {'type': 'function', '_funcname': '_methQueuePut',
4086
3975
  'args': (
4087
- {'name': 'item', 'type': 'prim', 'desc': 'The item being put into the queue.', },
3976
+ {'name': 'item', 'type': 'prim', 'desc': 'The item being put into the Queue.', },
4088
3977
  ),
4089
- 'returns': {'type': 'int', 'desc': 'The queue offset of the item.'}}},
3978
+ 'returns': {'type': 'int', 'desc': 'The Queue offset of the item.'}}},
4090
3979
  {'name': 'puts', 'desc': 'Put multiple items into the Queue.',
4091
3980
  'type': {'type': 'function', '_funcname': '_methQueuePuts',
4092
3981
  'args': (
4093
3982
  {'name': 'items', 'type': 'list', 'desc': 'The items to put into the Queue.', },
4094
3983
  ),
4095
- 'returns': {'type': 'int', 'desc': 'The queue offset of the first item.'}}},
3984
+ 'returns': {'type': 'int', 'desc': 'The Queue offset of the first item.'}}},
4096
3985
  {'name': 'gets', 'desc': 'Get multiple items from the Queue as a iterator.',
4097
3986
  'type': {'type': 'function', '_funcname': '_methQueueGets',
4098
3987
  'args': (
4099
- {'name': 'offs', 'type': 'int', 'desc': 'The offset to retrieve an items from.', 'default': 0, },
3988
+ {'name': 'offs', 'type': 'int', 'desc': 'The offset to retrieve items from.', 'default': 0, },
4100
3989
  {'name': 'wait', 'type': 'boolean', 'default': True,
4101
3990
  'desc': 'Wait for the offset to be available before returning the item.', },
4102
3991
  {'name': 'cull', 'type': 'boolean', 'default': False,
4103
3992
  'desc': 'Culls items up to, but not including, the specified offset.', },
4104
- {'name': 'size', 'type': 'int', 'desc': 'The maximum number of items to yield',
3993
+ {'name': 'size', 'type': 'int', 'desc': 'The maximum number of items to yield.',
4105
3994
  'default': None, },
4106
3995
  ),
4107
3996
  'returns': {'name': 'Yields', 'type': 'list', 'desc': 'Yields tuples of the offset and item.', }}},
4108
- {'name': 'cull', 'desc': 'Remove items from the queue up to, and including, the offset.',
3997
+ {'name': 'cull', 'desc': 'Remove items from the Queue up to, and including, the offset.',
4109
3998
  'type': {'type': 'function', '_funcname': '_methQueueCull',
4110
3999
  'args': (
4111
- {'name': 'offs', 'type': 'int', 'desc': 'The offset which to cull records from the queue.', },
4000
+ {'name': 'offs', 'type': 'int', 'desc': 'The offset which to cull records from the Queue.', },
4112
4001
  ),
4113
4002
  'returns': {'type': 'null', }}},
4114
4003
  {'name': 'size', 'desc': 'Get the number of items in the Queue.',
@@ -6096,45 +5985,6 @@ class LibVars(Lib):
6096
5985
  async def _libVarsType(self, valu):
6097
5986
  return await totype(valu)
6098
5987
 
6099
- @registry.registerType
6100
- class PkgVars(Prim):
6101
- '''
6102
- The Storm deref/setitem/iter convention on top of pkg vars information.
6103
- '''
6104
- _storm_typename = 'pkg:vars'
6105
- _ismutable = True
6106
-
6107
- def __init__(self, runt, valu, path=None):
6108
- Prim.__init__(self, valu, path=path)
6109
- self.runt = runt
6110
-
6111
- def _reqPkgAdmin(self):
6112
- confirm(('power-ups', self.valu, 'admin'))
6113
-
6114
- @stormfunc(readonly=True)
6115
- async def deref(self, name):
6116
- self._reqPkgAdmin()
6117
- name = await tostr(name)
6118
- return await self.runt.snap.core.getStormPkgVar(self.valu, name)
6119
-
6120
- async def setitem(self, name, valu):
6121
- self._reqPkgAdmin()
6122
- name = await tostr(name)
6123
-
6124
- if valu is undef:
6125
- await self.runt.snap.core.popStormPkgVar(self.valu, name)
6126
- return
6127
-
6128
- valu = await toprim(valu)
6129
- await self.runt.snap.core.setStormPkgVar(self.valu, name, valu)
6130
-
6131
- @stormfunc(readonly=True)
6132
- async def iter(self):
6133
- self._reqPkgAdmin()
6134
- async for name, valu in self.runt.snap.core.iterStormPkgVars(self.valu):
6135
- yield name, valu
6136
- await asyncio.sleep(0)
6137
-
6138
5988
  @registry.registerType
6139
5989
  class Query(Prim):
6140
5990
  '''
synapse/lib/trigger.py CHANGED
@@ -136,26 +136,28 @@ class Triggers:
136
136
  finally:
137
137
  RecursionDepth.reset(token)
138
138
 
139
- async def runNodeAdd(self, node):
139
+ async def runNodeAdd(self, node, useriden):
140
+ vars = {'auto': {'opts': {'user': useriden}}}
140
141
  with self._recursion_check():
141
- [await trig.execute(node) for trig in self.nodeadd.get(node.form.name, ())]
142
+ [await trig.execute(node, vars=vars) for trig in self.nodeadd.get(node.form.name, ())]
142
143
 
143
- async def runNodeDel(self, node):
144
+ async def runNodeDel(self, node, useriden):
145
+ vars = {'auto': {'opts': {'user': useriden}}}
144
146
  with self._recursion_check():
145
- [await trig.execute(node) for trig in self.nodedel.get(node.form.name, ())]
147
+ [await trig.execute(node, vars=vars) for trig in self.nodedel.get(node.form.name, ())]
146
148
 
147
- async def runPropSet(self, node, prop, oldv):
149
+ async def runPropSet(self, node, prop, oldv, useriden):
148
150
  vars = {'propname': prop.name, 'propfull': prop.full,
149
- 'auto': {'opts': {'propname': prop.name, 'propfull': prop.full, }},
151
+ 'auto': {'opts': {'propname': prop.name, 'propfull': prop.full, 'user': useriden}},
150
152
  }
151
153
  with self._recursion_check():
152
154
  [await trig.execute(node, vars=vars) for trig in self.propset.get(prop.full, ())]
153
155
  if prop.univ is not None:
154
156
  [await trig.execute(node, vars=vars) for trig in self.propset.get(prop.univ.full, ())]
155
157
 
156
- async def runTagAdd(self, node, tag):
158
+ async def runTagAdd(self, node, tag, useriden):
157
159
 
158
- vars = {'tag': tag, 'auto': {'opts': {'tag': tag}}}
160
+ vars = {'tag': tag, 'auto': {'opts': {'tag': tag, 'user': useriden}}}
159
161
  with self._recursion_check():
160
162
 
161
163
  for trig in self.tagadd.get((node.form.name, tag), ()):
@@ -176,10 +178,10 @@ class Triggers:
176
178
  for _, trig in globs.get(tag):
177
179
  await trig.execute(node, vars=vars)
178
180
 
179
- async def runTagDel(self, node, tag):
181
+ async def runTagDel(self, node, tag, useriden):
180
182
 
181
183
  vars = {'tag': tag,
182
- 'auto': {'opts': {'tag': tag}},
184
+ 'auto': {'opts': {'tag': tag, 'user': useriden}},
183
185
  }
184
186
  with self._recursion_check():
185
187
 
@@ -201,11 +203,11 @@ class Triggers:
201
203
  for _, trig in globs.get(tag):
202
204
  await trig.execute(node, vars=vars)
203
205
 
204
- async def runEdgeAdd(self, n1, verb, n2):
206
+ async def runEdgeAdd(self, n1, verb, n2, useriden):
205
207
  n1form = n1.form.name if n1 else None
206
208
  n2form = n2.form.name if n2 else None
207
209
  n2iden = n2.iden() if n2 else None
208
- varz = {'auto': {'opts': {'verb': verb, 'n2iden': n2iden}}}
210
+ varz = {'auto': {'opts': {'verb': verb, 'n2iden': n2iden, 'user': useriden}}}
209
211
  with self._recursion_check():
210
212
  cachekey = (n1form, verb, n2form)
211
213
  cached = self.edgeaddcache.get(cachekey)
@@ -251,11 +253,11 @@ class Triggers:
251
253
  for trig in cached:
252
254
  await trig.execute(n1, vars=varz)
253
255
 
254
- async def runEdgeDel(self, n1, verb, n2):
256
+ async def runEdgeDel(self, n1, verb, n2, useriden):
255
257
  n1form = n1.form.name if n1 else None
256
258
  n2form = n2.form.name if n2 else None
257
259
  n2iden = n2.iden() if n2 else None
258
- varz = {'auto': {'opts': {'verb': verb, 'n2iden': n2iden}}}
260
+ varz = {'auto': {'opts': {'verb': verb, 'n2iden': n2iden, 'user': useriden}}}
259
261
  with self._recursion_check():
260
262
  cachekey = (n1form, verb, n2form)
261
263
  cached = self.edgedelcache.get(cachekey)
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, 222, 0)
226
+ version = (2, 223, 0)
227
227
  verstring = '.'.join([str(x) for x in version])
228
- commit = '1ab0342cfb8272e9f9a629f1755b0e33b78b78b3'
228
+ commit = 'b40e64b75fa2820856ad138b8ad9f8c4b6e9547e'
synapse/lib/view.py CHANGED
@@ -58,6 +58,9 @@ class ViewApi(s_cell.CellApi):
58
58
  @s_cell.adminapi()
59
59
  async def saveNodeEdits(self, edits, meta):
60
60
  meta['link:user'] = self.user.iden
61
+ user = meta.get('user', '')
62
+ if not s_common.isguid(user):
63
+ raise s_exc.BadArg(mesg=f'Meta argument requires user key to be a guid, got {user=}')
61
64
  async with await self.view.snap(user=self.user) as snap:
62
65
  return await snap.saveNodeEdits(edits, meta)
63
66
 
@@ -1584,57 +1587,57 @@ class View(s_nexus.Pusher): # type: ignore
1584
1587
  layer = self.layers[0]
1585
1588
  await layer.confirmLayerEditPerms(user, layer.iden, delete=True)
1586
1589
 
1587
- async def runTagAdd(self, node, tag, valu):
1590
+ async def runTagAdd(self, node, tag, valu, useriden):
1588
1591
 
1589
1592
  if self.core.migration or self.core.safemode:
1590
1593
  return
1591
1594
 
1592
1595
  # Run any trigger handlers
1593
- await self.triggers.runTagAdd(node, tag)
1596
+ await self.triggers.runTagAdd(node, tag, useriden)
1594
1597
 
1595
- async def runTagDel(self, node, tag, valu):
1598
+ async def runTagDel(self, node, tag, valu, useriden):
1596
1599
 
1597
1600
  if self.core.migration or self.core.safemode:
1598
1601
  return
1599
1602
 
1600
- await self.triggers.runTagDel(node, tag)
1603
+ await self.triggers.runTagDel(node, tag, useriden)
1601
1604
 
1602
- async def runNodeAdd(self, node):
1605
+ async def runNodeAdd(self, node, useriden):
1603
1606
 
1604
1607
  if self.core.migration or self.core.safemode:
1605
1608
  return
1606
1609
 
1607
- await self.triggers.runNodeAdd(node)
1610
+ await self.triggers.runNodeAdd(node, useriden)
1608
1611
 
1609
- async def runNodeDel(self, node):
1612
+ async def runNodeDel(self, node, useriden):
1610
1613
 
1611
1614
  if self.core.migration or self.core.safemode:
1612
1615
  return
1613
1616
 
1614
- await self.triggers.runNodeDel(node)
1617
+ await self.triggers.runNodeDel(node, useriden)
1615
1618
 
1616
- async def runPropSet(self, node, prop, oldv):
1619
+ async def runPropSet(self, node, prop, oldv, useriden):
1617
1620
  '''
1618
1621
  Handle when a prop set trigger event fired
1619
1622
  '''
1620
1623
  if self.core.migration or self.core.safemode:
1621
1624
  return
1622
1625
 
1623
- await self.triggers.runPropSet(node, prop, oldv)
1626
+ await self.triggers.runPropSet(node, prop, oldv, useriden)
1624
1627
 
1625
- async def runEdgeAdd(self, n1, edge, n2):
1628
+ async def runEdgeAdd(self, n1, edge, n2, useriden):
1626
1629
 
1627
1630
  if self.core.migration or self.core.safemode:
1628
1631
  return
1629
1632
 
1630
- await self.triggers.runEdgeAdd(n1, edge, n2)
1633
+ await self.triggers.runEdgeAdd(n1, edge, n2, useriden)
1631
1634
 
1632
- async def runEdgeDel(self, n1, edge, n2):
1635
+ async def runEdgeDel(self, n1, edge, n2, useriden):
1633
1636
 
1634
1637
  if self.core.migration or self.core.safemode:
1635
1638
  return
1636
1639
 
1637
- await self.triggers.runEdgeDel(n1, edge, n2)
1640
+ await self.triggers.runEdgeDel(n1, edge, n2, useriden)
1638
1641
 
1639
1642
  async def addTrigger(self, tdef):
1640
1643
  '''
synapse/models/files.py CHANGED
@@ -390,7 +390,7 @@ class FileModule(s_module.CoreModule):
390
390
  'doc': 'The typecode for the resource.',
391
391
  }),
392
392
 
393
- ('pe:langid', ('int', {'enums': s_l_pe.getLangCodes()}), {
393
+ ('pe:langid', ('int', {'min': 0, 'max': 0xffff, 'enums': s_l_pe.getLangCodes(), 'enums:strict': False}), {
394
394
  'doc': 'The PE language id.',
395
395
  }),
396
396
 
@@ -426,7 +426,7 @@ class CortexTest(s_t_utils.SynTest):
426
426
  self.len(1, await core00.nodes('test:str=foo', opts=view00opts))
427
427
 
428
428
  layr = core01.getLayer(layr01iden)
429
- await layr.storNodeEdits((), {})
429
+ await layr.storNodeEdits((), {'user': s_common.guid()})
430
430
 
431
431
  async def test_cortex_must_upgrade(self):
432
432