synapse 2.209.0__py311-none-any.whl → 2.211.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/lib/base.py +2 -3
- synapse/lib/cell.py +14 -4
- synapse/lib/coro.py +5 -0
- synapse/lib/json.py +48 -22
- synapse/lib/nexus.py +6 -0
- synapse/lib/node.py +1 -1
- synapse/lib/schemas.py +10 -1
- synapse/lib/share.py +0 -3
- synapse/lib/snap.py +3 -0
- synapse/lib/storm.py +10 -2
- synapse/lib/stormlib/auth.py +6 -0
- synapse/lib/stormlib/notifications.py +12 -2
- synapse/lib/stormtypes.py +2 -2
- synapse/lib/version.py +2 -2
- synapse/models/entity.py +26 -0
- synapse/models/inet.py +55 -0
- synapse/models/orgs.py +0 -1
- synapse/models/person.py +9 -2
- synapse/tests/test_cortex.py +3 -3
- synapse/tests/test_lib_aha.py +1 -1
- synapse/tests/test_lib_base.py +5 -0
- synapse/tests/test_lib_cell.py +28 -8
- synapse/tests/test_lib_coro.py +23 -0
- synapse/tests/test_lib_json.py +41 -16
- synapse/tests/test_lib_storm.py +20 -0
- synapse/tests/test_lib_stormtypes.py +16 -18
- synapse/tests/test_lib_view.py +14 -0
- synapse/tests/test_model_entity.py +21 -0
- synapse/tests/test_model_gov_intl.py +2 -2
- synapse/tests/test_model_inet.py +30 -0
- synapse/tests/test_model_media.py +1 -0
- synapse/tests/test_model_orgs.py +18 -2
- synapse/tests/test_model_person.py +12 -0
- synapse/tests/test_telepath.py +52 -41
- synapse/tests/test_tools_aha.py +7 -8
- synapse/tests/test_tools_genpkg.py +9 -0
- synapse/tests/utils.py +1 -1
- synapse/tools/aha/clone.py +7 -1
- synapse/tools/aha/easycert.py +37 -42
- synapse/tools/aha/enroll.py +7 -1
- synapse/tools/aha/list.py +60 -65
- synapse/tools/aha/mirror.py +7 -1
- synapse/tools/aha/provision/service.py +7 -1
- synapse/tools/aha/provision/user.py +7 -1
- synapse/tools/apikey.py +8 -1
- synapse/tools/autodoc.py +8 -2
- synapse/tools/axon2axon.py +7 -1
- synapse/tools/cellauth.py +6 -5
- synapse/tools/cmdr.py +2 -1
- synapse/tools/csvtool.py +7 -2
- synapse/tools/feed.py +8 -2
- synapse/tools/genpkg.py +16 -3
- synapse/tools/healthcheck.py +7 -1
- synapse/tools/livebackup.py +7 -3
- synapse/tools/modrole.py +7 -1
- synapse/tools/moduser.py +7 -2
- synapse/tools/promote.py +7 -3
- synapse/tools/pullfile.py +6 -1
- synapse/tools/pushfile.py +7 -1
- synapse/tools/reload.py +7 -4
- synapse/tools/rstorm.py +8 -2
- synapse/tools/snapshot.py +7 -1
- synapse/tools/storm.py +7 -1
- {synapse-2.209.0.dist-info → synapse-2.211.0.dist-info}/METADATA +2 -2
- {synapse-2.209.0.dist-info → synapse-2.211.0.dist-info}/RECORD +68 -67
- {synapse-2.209.0.dist-info → synapse-2.211.0.dist-info}/WHEEL +1 -1
- {synapse-2.209.0.dist-info → synapse-2.211.0.dist-info}/licenses/LICENSE +0 -0
- {synapse-2.209.0.dist-info → synapse-2.211.0.dist-info}/top_level.txt +0 -0
synapse/lib/base.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import gc
|
|
2
2
|
import os
|
|
3
|
+
import sys
|
|
3
4
|
import atexit
|
|
4
5
|
import signal
|
|
5
6
|
import asyncio
|
|
@@ -82,7 +83,7 @@ class Base:
|
|
|
82
83
|
'''
|
|
83
84
|
def __init__(self):
|
|
84
85
|
self.anitted = False
|
|
85
|
-
assert
|
|
86
|
+
assert sys._getframe(1).f_code.co_name == 'anit', 'Objects from Base must be constructed solely via "anit"'
|
|
86
87
|
|
|
87
88
|
@classmethod
|
|
88
89
|
async def anit(cls, *args, **kwargs):
|
|
@@ -129,7 +130,6 @@ class Base:
|
|
|
129
130
|
self.isfini = False
|
|
130
131
|
self.anitted = True # For assertion purposes
|
|
131
132
|
self.finievt = asyncio.Event()
|
|
132
|
-
self.entered = False
|
|
133
133
|
|
|
134
134
|
# hold a weak ref to other bases we should fini if they
|
|
135
135
|
# are still around when we go down...
|
|
@@ -205,7 +205,6 @@ class Base:
|
|
|
205
205
|
|
|
206
206
|
async def __aenter__(self):
|
|
207
207
|
assert asyncio.get_running_loop() == self.loop
|
|
208
|
-
self.entered = True
|
|
209
208
|
return self
|
|
210
209
|
|
|
211
210
|
async def __aexit__(self, exc, cls, tb):
|
synapse/lib/cell.py
CHANGED
|
@@ -2220,14 +2220,24 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
2220
2220
|
|
|
2221
2221
|
logger.debug(f'HANDOFF: Connected to {s_urlhelp.sanitizeUrl(turl)}{_dispname}.')
|
|
2222
2222
|
|
|
2223
|
-
|
|
2223
|
+
cellinfo = await cell.getCellInfo()
|
|
2224
|
+
cnfo = cellinfo.get('cell')
|
|
2225
|
+
if self.iden != cnfo.get('iden'): # pragma: no cover
|
|
2224
2226
|
mesg = 'Mirror handoff remote cell iden does not match!'
|
|
2225
2227
|
raise s_exc.BadArg(mesg=mesg)
|
|
2226
2228
|
|
|
2227
|
-
if self.runid ==
|
|
2229
|
+
if self.runid == cnfo.get('run'): # pragma: no cover
|
|
2228
2230
|
mesg = 'Cannot handoff mirror leadership to myself!'
|
|
2229
2231
|
raise s_exc.BadArg(mesg=mesg)
|
|
2230
2232
|
|
|
2233
|
+
ahalead = cnfo.get('aha', {}).get('leader')
|
|
2234
|
+
mirror_url = turl
|
|
2235
|
+
if turl.startswith('aha://') and ahalead is not None:
|
|
2236
|
+
ahauser = self.conf.get('aha:user')
|
|
2237
|
+
if ahauser is not None:
|
|
2238
|
+
ahauser = f'{ahauser}@'
|
|
2239
|
+
mirror_url = f'aha://{ahauser}{ahalead}...'
|
|
2240
|
+
|
|
2231
2241
|
logger.debug(f'HANDOFF: Obtaining nexus lock{_dispname}.')
|
|
2232
2242
|
|
|
2233
2243
|
async with self.nexslock:
|
|
@@ -2247,8 +2257,8 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
2247
2257
|
logger.debug(f'HANDOFF: Setting the service as inactive{_dispname}.')
|
|
2248
2258
|
await self.setCellActive(False)
|
|
2249
2259
|
|
|
2250
|
-
logger.debug(f'HANDOFF: Configuring service to sync from new leader{_dispname}.')
|
|
2251
|
-
self.modCellConf({'mirror':
|
|
2260
|
+
logger.debug(f'HANDOFF: Configuring service to sync from new leader{_dispname} @ {s_urlhelp.sanitizeUrl(mirror_url)}.')
|
|
2261
|
+
self.modCellConf({'mirror': mirror_url})
|
|
2252
2262
|
|
|
2253
2263
|
logger.debug(f'HANDOFF: Restarting the nexus{_dispname}.')
|
|
2254
2264
|
await self.nexsroot.startup()
|
synapse/lib/coro.py
CHANGED
synapse/lib/json.py
CHANGED
|
@@ -7,7 +7,7 @@ from typing import Any, BinaryIO, Callable, Iterator, Optional
|
|
|
7
7
|
|
|
8
8
|
from synapse.vendor.cpython.lib.json import detect_encoding
|
|
9
9
|
|
|
10
|
-
import
|
|
10
|
+
import yyjson
|
|
11
11
|
|
|
12
12
|
import synapse.exc as s_exc
|
|
13
13
|
|
|
@@ -37,8 +37,9 @@ def loads(s: str | bytes) -> Any:
|
|
|
37
37
|
deserializing the provided data.
|
|
38
38
|
'''
|
|
39
39
|
try:
|
|
40
|
-
return
|
|
41
|
-
|
|
40
|
+
return yyjson.Document(s, flags=yyjson.ReaderFlags.BIGNUM_AS_RAW).as_obj
|
|
41
|
+
|
|
42
|
+
except (ValueError, TypeError) as exc:
|
|
42
43
|
extra = {'synapse': {'fn': 'loads', 'reason': str(exc)}}
|
|
43
44
|
logger.warning('Using fallback JSON deserialization. Please report this to Vertex.', extra=extra)
|
|
44
45
|
return _fallback_loads(s)
|
|
@@ -70,6 +71,33 @@ def _fallback_dumps(obj: Any, sort_keys: bool = False, indent: bool = False, def
|
|
|
70
71
|
except TypeError as exc:
|
|
71
72
|
raise s_exc.MustBeJsonSafe(mesg=exc.args[0])
|
|
72
73
|
|
|
74
|
+
def _dumps(obj, sort_keys=False, indent=False, default=None, newline=False):
|
|
75
|
+
rflags = 0
|
|
76
|
+
wflags = 0
|
|
77
|
+
|
|
78
|
+
if sort_keys:
|
|
79
|
+
rflags |= yyjson.ReaderFlags.SORT_KEYS
|
|
80
|
+
|
|
81
|
+
if indent:
|
|
82
|
+
wflags |= yyjson.WriterFlags.PRETTY_TWO_SPACES
|
|
83
|
+
|
|
84
|
+
if newline:
|
|
85
|
+
wflags |= yyjson.WriterFlags.WRITE_NEWLINE_AT_END
|
|
86
|
+
|
|
87
|
+
if isinstance(obj, bytes):
|
|
88
|
+
mesg = 'Object of type bytes is not JSON serializable'
|
|
89
|
+
raise s_exc.MustBeJsonSafe(mesg=mesg)
|
|
90
|
+
|
|
91
|
+
# Raw strings have to be double-quoted. This is because the default behavior for `yyjson.Document`
|
|
92
|
+
# is to attempt to parse the string as a serialized JSON string into objects, so we escape string
|
|
93
|
+
# values so we can get the JSON encoded string as output.
|
|
94
|
+
if isinstance(obj, str) and obj not in ('null', 'true', 'false'):
|
|
95
|
+
# TODO in 3xx convert this into obj = f'''"{obj.replace('"', '\\"')}"'''
|
|
96
|
+
obj = ''.join(('"', obj.replace('"', '\\"'), '"'))
|
|
97
|
+
|
|
98
|
+
doc = yyjson.Document(obj, default=default, flags=rflags)
|
|
99
|
+
return doc.dumps(flags=wflags).encode()
|
|
100
|
+
|
|
73
101
|
def dumps(obj: Any, sort_keys: bool = False, indent: bool = False, default: Optional[Callable] = None, newline: bool = False) -> bytes:
|
|
74
102
|
'''
|
|
75
103
|
Serialize a python object to byte string.
|
|
@@ -89,24 +117,9 @@ def dumps(obj: Any, sort_keys: bool = False, indent: bool = False, default: Opti
|
|
|
89
117
|
Raises:
|
|
90
118
|
synapse.exc.MustBeJsonSafe: This exception is raised when a python object cannot be serialized.
|
|
91
119
|
'''
|
|
92
|
-
opts = 0
|
|
93
|
-
|
|
94
|
-
if indent:
|
|
95
|
-
opts |= orjson.OPT_INDENT_2
|
|
96
|
-
|
|
97
|
-
if sort_keys:
|
|
98
|
-
opts |= orjson.OPT_SORT_KEYS
|
|
99
|
-
|
|
100
|
-
if newline:
|
|
101
|
-
opts |= orjson.OPT_APPEND_NEWLINE
|
|
102
|
-
|
|
103
120
|
try:
|
|
104
|
-
return
|
|
105
|
-
|
|
106
|
-
except orjson.JSONEncodeError as exc:
|
|
107
|
-
if not isinstance(exc.__cause__, UnicodeEncodeError):
|
|
108
|
-
raise s_exc.MustBeJsonSafe(mesg=exc.args[0])
|
|
109
|
-
|
|
121
|
+
return _dumps(obj, sort_keys=sort_keys, indent=indent, default=default, newline=newline)
|
|
122
|
+
except UnicodeEncodeError as exc:
|
|
110
123
|
extra = {'synapse': {'fn': 'dumps', 'reason': str(exc)}}
|
|
111
124
|
logger.warning('Using fallback JSON serialization. Please report this to Vertex.', extra=extra)
|
|
112
125
|
|
|
@@ -117,6 +130,10 @@ def dumps(obj: Any, sort_keys: bool = False, indent: bool = False, default: Opti
|
|
|
117
130
|
|
|
118
131
|
return ret
|
|
119
132
|
|
|
133
|
+
except (TypeError, ValueError) as exc:
|
|
134
|
+
mesg = f'{exc.__class__.__name__}: {exc}'
|
|
135
|
+
raise s_exc.MustBeJsonSafe(mesg=mesg)
|
|
136
|
+
|
|
120
137
|
def dump(obj: Any, fp: BinaryIO, sort_keys: bool = False, indent: bool = False, default: Optional[Callable] = None, newline: bool = False) -> None:
|
|
121
138
|
'''
|
|
122
139
|
Serialize a python object to a file-like object opened in binary mode.
|
|
@@ -217,8 +234,17 @@ def reqjsonsafe(item: Any, strict: bool = False) -> None:
|
|
|
217
234
|
'''
|
|
218
235
|
if strict:
|
|
219
236
|
try:
|
|
220
|
-
|
|
237
|
+
_dumps(item)
|
|
238
|
+
|
|
239
|
+
except s_exc.MustBeJsonSafe:
|
|
240
|
+
raise
|
|
241
|
+
|
|
242
|
+
except UnicodeEncodeError as exc:
|
|
243
|
+
mesg = str(exc)
|
|
244
|
+
raise s_exc.MustBeJsonSafe(mesg=mesg)
|
|
245
|
+
|
|
221
246
|
except Exception as exc:
|
|
222
|
-
|
|
247
|
+
mesg = f'{exc.__class__.__name__}: {exc}'
|
|
248
|
+
raise s_exc.MustBeJsonSafe(mesg=mesg)
|
|
223
249
|
else:
|
|
224
250
|
dumps(item)
|
synapse/lib/nexus.py
CHANGED
|
@@ -506,6 +506,7 @@ class NexsRoot(s_base.Base):
|
|
|
506
506
|
|
|
507
507
|
async def runMirrorLoop(self, proxy):
|
|
508
508
|
|
|
509
|
+
cellinfo = None
|
|
509
510
|
try:
|
|
510
511
|
cellinfo = await proxy.getCellInfo()
|
|
511
512
|
features = cellinfo.get('features', {})
|
|
@@ -536,6 +537,11 @@ class NexsRoot(s_base.Base):
|
|
|
536
537
|
|
|
537
538
|
while not proxy.isfini:
|
|
538
539
|
|
|
540
|
+
if cellinfo:
|
|
541
|
+
ahaname = cellinfo.get('cell').get('aha', {}).get('name')
|
|
542
|
+
if ahaname:
|
|
543
|
+
logger.info(f'Mirror communicating with aha service {ahaname}')
|
|
544
|
+
|
|
539
545
|
try:
|
|
540
546
|
|
|
541
547
|
if self.readonly:
|
synapse/lib/node.py
CHANGED
|
@@ -181,7 +181,7 @@ class Node:
|
|
|
181
181
|
|
|
182
182
|
if prop.modl.form(prop.type.name) is not None:
|
|
183
183
|
buid = s_common.buid((prop.type.name, valu))
|
|
184
|
-
elif prop.type.name == 'ndef':
|
|
184
|
+
elif prop.type.name == 'ndef' or 'ndef' in prop.type.info.get('bases'):
|
|
185
185
|
buid = s_common.buid(valu)
|
|
186
186
|
else:
|
|
187
187
|
return None
|
synapse/lib/schemas.py
CHANGED
|
@@ -668,9 +668,18 @@ _reqValidPkgdefSchema = {
|
|
|
668
668
|
'pattern': s_version.semverstr,
|
|
669
669
|
},
|
|
670
670
|
'build': {
|
|
671
|
-
'type' 'object'
|
|
671
|
+
'type': 'object',
|
|
672
672
|
'properties': {
|
|
673
673
|
'time': {'type': 'number'},
|
|
674
|
+
'synapse:version': {
|
|
675
|
+
'type': 'string',
|
|
676
|
+
'pattern': s_version.semverstr
|
|
677
|
+
},
|
|
678
|
+
'synapse:commit': {
|
|
679
|
+
'type': 'string',
|
|
680
|
+
# Note: This pattern allows empty string for dev environments
|
|
681
|
+
'pattern': '^[0-9a-fA-F]*$'
|
|
682
|
+
},
|
|
674
683
|
},
|
|
675
684
|
'required': ['time'],
|
|
676
685
|
},
|
synapse/lib/share.py
CHANGED
synapse/lib/snap.py
CHANGED
synapse/lib/storm.py
CHANGED
|
@@ -174,6 +174,14 @@ Examples:
|
|
|
174
174
|
cron.at --dt 20181231Z2359 {[inet:ipv4=1]}
|
|
175
175
|
'''
|
|
176
176
|
|
|
177
|
+
viewdeldescr = '''
|
|
178
|
+
Delete a view from the cortex.
|
|
179
|
+
|
|
180
|
+
Notes:
|
|
181
|
+
Deleting a view with the `view.del` command does not delete any of the layers in the view.
|
|
182
|
+
To delete layers, you must use the `layer.del` command separately.
|
|
183
|
+
'''
|
|
184
|
+
|
|
177
185
|
wgetdescr = '''Retrieve bytes from a URL and store them in the axon. Yields inet:urlfile nodes.
|
|
178
186
|
|
|
179
187
|
Examples:
|
|
@@ -656,7 +664,7 @@ stormcmds = (
|
|
|
656
664
|
},
|
|
657
665
|
{
|
|
658
666
|
'name': 'view.del',
|
|
659
|
-
'descr':
|
|
667
|
+
'descr': viewdeldescr,
|
|
660
668
|
'cmdargs': (
|
|
661
669
|
('iden', {'help': 'Iden of the view to delete.'}),
|
|
662
670
|
),
|
|
@@ -2056,7 +2064,7 @@ class Runtime(s_base.Base):
|
|
|
2056
2064
|
continue
|
|
2057
2065
|
|
|
2058
2066
|
if len(nodes) == 1:
|
|
2059
|
-
mesg = 'Ambiguous value for single node lookup: {propname}
|
|
2067
|
+
mesg = f'Ambiguous value for single node lookup: {propname}{cmpr}{valu}'
|
|
2060
2068
|
raise s_exc.StormRuntimeError(mesg=mesg)
|
|
2061
2069
|
|
|
2062
2070
|
nodes.append(node)
|
synapse/lib/stormlib/auth.py
CHANGED
|
@@ -901,12 +901,14 @@ class User(s_stormtypes.Prim):
|
|
|
901
901
|
),
|
|
902
902
|
'returns': {'type': 'null', }}},
|
|
903
903
|
{'name': 'tell', 'desc': 'Send a tell notification to a user.',
|
|
904
|
+
'deprecated': {'eolvers': 'v3.0.0'},
|
|
904
905
|
'type': {'type': 'function', '_funcname': '_methUserTell',
|
|
905
906
|
'args': (
|
|
906
907
|
{'name': 'text', 'type': 'str', 'desc': 'The text of the message to send.', },
|
|
907
908
|
),
|
|
908
909
|
'returns': {'type': 'null', }}},
|
|
909
910
|
{'name': 'notify', 'desc': 'Send an arbitrary user notification.',
|
|
911
|
+
'deprecated': {'eolvers': 'v3.0.0'},
|
|
910
912
|
'type': {'type': 'function', '_funcname': '_methUserNotify',
|
|
911
913
|
'args': (
|
|
912
914
|
{'name': 'mesgtype', 'type': 'str', 'desc': 'The notification type.', },
|
|
@@ -1153,6 +1155,8 @@ class User(s_stormtypes.Prim):
|
|
|
1153
1155
|
return await self.value()
|
|
1154
1156
|
|
|
1155
1157
|
async def _methUserTell(self, text):
|
|
1158
|
+
s_common.deprecated('user.tell()', '2.210.0', '3.0.0')
|
|
1159
|
+
await self.runt.snap.warnonce('user.tell() is deprecated.')
|
|
1156
1160
|
self.runt.confirm(('tell', self.valu), default=True)
|
|
1157
1161
|
mesgdata = {
|
|
1158
1162
|
'text': await s_stormtypes.tostr(text),
|
|
@@ -1161,6 +1165,8 @@ class User(s_stormtypes.Prim):
|
|
|
1161
1165
|
return await self.runt.snap.core.addUserNotif(self.valu, 'tell', mesgdata)
|
|
1162
1166
|
|
|
1163
1167
|
async def _methUserNotify(self, mesgtype, mesgdata):
|
|
1168
|
+
s_common.deprecated('user.notify()', '2.210.0', '3.0.0')
|
|
1169
|
+
await self.runt.snap.warnonce('user.notify() is deprecated.')
|
|
1164
1170
|
if not self.runt.isAdmin():
|
|
1165
1171
|
mesg = '$user.notify() method requires admin privs.'
|
|
1166
1172
|
raise s_exc.AuthDeny(mesg=mesg, user=self.runt.user.iden, username=self.runt.user.name)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import synapse.exc as s_exc
|
|
2
|
+
import synapse.common as s_common
|
|
3
|
+
|
|
2
4
|
import synapse.lib.stormtypes as s_stormtypes
|
|
3
5
|
|
|
4
6
|
@s_stormtypes.registry.registerLib
|
|
@@ -12,6 +14,7 @@ class NotifyLib(s_stormtypes.Lib):
|
|
|
12
14
|
Yield (<indx>, <mesg>) tuples for a user's notifications.
|
|
13
15
|
|
|
14
16
|
''',
|
|
17
|
+
'deprecated': {'eolvers': 'v3.0.0'},
|
|
15
18
|
'type': {
|
|
16
19
|
'type': 'function', '_funcname': 'list',
|
|
17
20
|
'args': (
|
|
@@ -28,6 +31,7 @@ class NotifyLib(s_stormtypes.Lib):
|
|
|
28
31
|
Delete a previously delivered notification.
|
|
29
32
|
|
|
30
33
|
''',
|
|
34
|
+
'deprecated': {'eolvers': 'v3.0.0'},
|
|
31
35
|
'type': {
|
|
32
36
|
'type': 'function', '_funcname': '_del',
|
|
33
37
|
'args': (
|
|
@@ -44,6 +48,7 @@ class NotifyLib(s_stormtypes.Lib):
|
|
|
44
48
|
Return a notification by ID (or ``(null)`` ).
|
|
45
49
|
|
|
46
50
|
''',
|
|
51
|
+
'deprecated': {'eolvers': 'v3.0.0'},
|
|
47
52
|
'type': {
|
|
48
53
|
'type': 'function', '_funcname': 'get',
|
|
49
54
|
'args': (
|
|
@@ -55,20 +60,21 @@ class NotifyLib(s_stormtypes.Lib):
|
|
|
55
60
|
},
|
|
56
61
|
},
|
|
57
62
|
)
|
|
63
|
+
_storm_lib_deprecation = {'eolvers': 'v3.0.0'}
|
|
58
64
|
|
|
59
65
|
def getObjLocals(self):
|
|
60
66
|
return {
|
|
61
67
|
'get': self.get,
|
|
62
68
|
'del': self._del,
|
|
63
69
|
'list': self.list,
|
|
64
|
-
# 'bytime':
|
|
65
|
-
# 'bytype':
|
|
66
70
|
}
|
|
67
71
|
|
|
68
72
|
@s_stormtypes.stormfunc(readonly=True)
|
|
69
73
|
async def get(self, indx):
|
|
70
74
|
indx = await s_stormtypes.toint(indx)
|
|
71
75
|
mesg = await self.runt.snap.core.getUserNotif(indx)
|
|
76
|
+
s_common.deprecated('$lib.notifications.get()', '2.210.0', '3.0.0')
|
|
77
|
+
await self.runt.snap.warnonce('$lib.notifications.get() is deprecated.')
|
|
72
78
|
if mesg[0] != self.runt.user.iden and not self.runt.isAdmin():
|
|
73
79
|
mesg = 'You may only get notifications which belong to you.'
|
|
74
80
|
raise s_exc.AuthDeny(mesg=mesg, user=self.runt.user.iden, username=self.runt.user.name)
|
|
@@ -77,6 +83,8 @@ class NotifyLib(s_stormtypes.Lib):
|
|
|
77
83
|
async def _del(self, indx):
|
|
78
84
|
indx = await s_stormtypes.toint(indx)
|
|
79
85
|
mesg = await self.runt.snap.core.getUserNotif(indx)
|
|
86
|
+
s_common.deprecated('$lib.notifications.del()', '2.210.0', '3.0.0')
|
|
87
|
+
await self.runt.snap.warnonce('$lib.notifications.del() is deprecated.')
|
|
80
88
|
if mesg[0] != self.runt.user.iden and not self.runt.isAdmin():
|
|
81
89
|
mesg = 'You may only delete notifications which belong to you.'
|
|
82
90
|
raise s_exc.AuthDeny(mesg=mesg, user=self.runt.user.iden, username=self.runt.user.name)
|
|
@@ -85,5 +93,7 @@ class NotifyLib(s_stormtypes.Lib):
|
|
|
85
93
|
@s_stormtypes.stormfunc(readonly=True)
|
|
86
94
|
async def list(self, size=None):
|
|
87
95
|
size = await s_stormtypes.toint(size, noneok=True)
|
|
96
|
+
s_common.deprecated('$lib.notifications.list()', '2.210.0', '3.0.0')
|
|
97
|
+
await self.runt.snap.warnonce('$lib.notifications.list() is deprecated.')
|
|
88
98
|
async for mesg in self.runt.snap.core.iterUserNotifs(self.runt.user.iden, size=size):
|
|
89
99
|
yield mesg
|
synapse/lib/stormtypes.py
CHANGED
|
@@ -6210,9 +6210,9 @@ class NodeData(Prim):
|
|
|
6210
6210
|
{'name': 'valu', 'type': 'prim', 'desc': 'The data to store.', },
|
|
6211
6211
|
),
|
|
6212
6212
|
'returns': {'type': 'null', }}},
|
|
6213
|
-
{'name': 'list', 'desc': 'Get a list of the Node data
|
|
6213
|
+
{'name': 'list', 'desc': 'Get a list of the Node data on the Node as (name, value) tuples.',
|
|
6214
6214
|
'type': {'type': 'function', '_funcname': '_listNodeData',
|
|
6215
|
-
'returns': {'type': 'list', 'desc': 'List of
|
|
6215
|
+
'returns': {'type': 'list', 'desc': 'List of (name, value) tuples stored on the node.', }}},
|
|
6216
6216
|
{'name': 'load',
|
|
6217
6217
|
'desc': 'Load the Node data onto the Node so that the Node data is packed and returned by the runtime.',
|
|
6218
6218
|
'type': {'type': 'function', '_funcname': '_loadNodeData',
|
synapse/lib/version.py
CHANGED
|
@@ -223,6 +223,6 @@ def reqVersion(valu, reqver,
|
|
|
223
223
|
##############################################################################
|
|
224
224
|
# The following are touched during the release process by bumpversion.
|
|
225
225
|
# Do not modify these directly.
|
|
226
|
-
version = (2,
|
|
226
|
+
version = (2, 211, 0)
|
|
227
227
|
verstring = '.'.join([str(x) for x in version])
|
|
228
|
-
commit = '
|
|
228
|
+
commit = '99beab651131ab996a967c6d0345c80b89de4a74'
|
synapse/models/entity.py
CHANGED
|
@@ -8,9 +8,35 @@ class EntityModule(s_module.CoreModule):
|
|
|
8
8
|
'types': (
|
|
9
9
|
('entity:name', ('str', {'onespace': True, 'lower': True}), {
|
|
10
10
|
'doc': 'A name used to refer to an entity.'}),
|
|
11
|
+
|
|
12
|
+
('entity:actor', ('ndef', {'forms': ('ou:org', 'ps:person', 'ps:contact', 'risk:threat')}), {
|
|
13
|
+
'doc': 'An entity which has initiative to act.'}),
|
|
14
|
+
|
|
15
|
+
('entity:relationship:type:taxonomy', ('taxonomy', {}), {
|
|
16
|
+
'interfaces': ('meta:taxonomy', ),
|
|
17
|
+
'doc': 'A hierarchical taxonomy of entity relationship types.'}),
|
|
18
|
+
|
|
19
|
+
('entity:relationship', ('guid', {}), {
|
|
20
|
+
'doc': 'A directional relationship between two actor entities.'}),
|
|
11
21
|
),
|
|
12
22
|
|
|
13
23
|
'forms': (
|
|
14
24
|
('entity:name', {}, ()),
|
|
25
|
+
|
|
26
|
+
('entity:relationship:type:taxonomy', {}, ()),
|
|
27
|
+
('entity:relationship', {}, (
|
|
28
|
+
|
|
29
|
+
('type', ('entity:relationship:type:taxonomy', {}), {
|
|
30
|
+
'doc': 'The type of relationship.'}),
|
|
31
|
+
|
|
32
|
+
('period', ('ival', {}), {
|
|
33
|
+
'doc': 'The time period when the relationship existed.'}),
|
|
34
|
+
|
|
35
|
+
('source', ('entity:actor', {}), {
|
|
36
|
+
'doc': 'The source entity in the relationship.'}),
|
|
37
|
+
|
|
38
|
+
('target', ('entity:actor', {}), {
|
|
39
|
+
'doc': 'The target entity in the relationship.'}),
|
|
40
|
+
)),
|
|
15
41
|
),
|
|
16
42
|
}),)
|
synapse/models/inet.py
CHANGED
|
@@ -1535,6 +1535,11 @@ class InetModule(s_module.CoreModule):
|
|
|
1535
1535
|
('inet:service:platform', ('guid', {}), {
|
|
1536
1536
|
'doc': 'A network platform which provides services.'}),
|
|
1537
1537
|
|
|
1538
|
+
('inet:service:app', ('guid', {}), {
|
|
1539
|
+
'interfaces': ('inet:service:object',),
|
|
1540
|
+
'template': {'service:base': 'application'},
|
|
1541
|
+
'doc': 'A platform specific application.'}),
|
|
1542
|
+
|
|
1538
1543
|
('inet:service:instance', ('guid', {}), {
|
|
1539
1544
|
'doc': 'An instance of the platform such as Slack or Discord instances.'}),
|
|
1540
1545
|
|
|
@@ -1626,6 +1631,10 @@ class InetModule(s_module.CoreModule):
|
|
|
1626
1631
|
'template': {'service:base': 'emote'},
|
|
1627
1632
|
'doc': 'An emote or reaction by an account.'}),
|
|
1628
1633
|
|
|
1634
|
+
('inet:service:access:action:taxonomy', ('taxonomy', {}), {
|
|
1635
|
+
'interfaces': ('meta:taxonomy',),
|
|
1636
|
+
'doc': 'A hierarchical taxonomy of service actions.'}),
|
|
1637
|
+
|
|
1629
1638
|
('inet:service:access', ('guid', {}), {
|
|
1630
1639
|
'interfaces': ('inet:service:action',),
|
|
1631
1640
|
'doc': 'Represents a user access request to a service resource.'}),
|
|
@@ -1774,6 +1783,9 @@ class InetModule(s_module.CoreModule):
|
|
|
1774
1783
|
'interfaces': ('inet:service:base',),
|
|
1775
1784
|
'props': (
|
|
1776
1785
|
|
|
1786
|
+
('app', ('inet:service:app', {}), {
|
|
1787
|
+
'doc': 'The app which handled the action.'}),
|
|
1788
|
+
|
|
1777
1789
|
('time', ('time', {}), {
|
|
1778
1790
|
'doc': 'The time that the account initiated the action.'}),
|
|
1779
1791
|
|
|
@@ -1807,6 +1819,9 @@ class InetModule(s_module.CoreModule):
|
|
|
1807
1819
|
('client:host', ('it:host', {}), {
|
|
1808
1820
|
'doc': 'The client host which initiated the action.'}),
|
|
1809
1821
|
|
|
1822
|
+
('client:app', ('inet:service:app', {}), {
|
|
1823
|
+
'doc': 'The client service app which initiated the action.'}),
|
|
1824
|
+
|
|
1810
1825
|
('server', ('inet:server', {}), {
|
|
1811
1826
|
'doc': 'The network address of the server which handled the action.'}),
|
|
1812
1827
|
|
|
@@ -3608,12 +3623,22 @@ class InetModule(s_module.CoreModule):
|
|
|
3608
3623
|
|
|
3609
3624
|
('url', ('inet:url', {}), {
|
|
3610
3625
|
'ex': 'https://twitter.com',
|
|
3626
|
+
'alts': ('urls',),
|
|
3611
3627
|
'doc': 'The primary URL of the platform.'}),
|
|
3612
3628
|
|
|
3629
|
+
('urls', ('array', {'type': 'inet:url', 'sorted': True, 'uniq': True}), {
|
|
3630
|
+
'doc': 'An array of alternate URLs for the platform.'}),
|
|
3631
|
+
|
|
3613
3632
|
('name', ('str', {'onespace': True, 'lower': True}), {
|
|
3614
3633
|
'ex': 'twitter',
|
|
3634
|
+
'alts': ('names',),
|
|
3615
3635
|
'doc': 'A friendly name for the platform.'}),
|
|
3616
3636
|
|
|
3637
|
+
('names', ('array', {'type': 'str',
|
|
3638
|
+
'typeopts': {'onespace': True, 'lower': True},
|
|
3639
|
+
'sorted': True, 'uniq': True}), {
|
|
3640
|
+
'doc': 'An array of alternate names for the platform.'}),
|
|
3641
|
+
|
|
3617
3642
|
('desc', ('str', {}), {
|
|
3618
3643
|
'disp': {'hint': 'text'},
|
|
3619
3644
|
'doc': 'A description of the service platform.'}),
|
|
@@ -3662,6 +3687,22 @@ class InetModule(s_module.CoreModule):
|
|
|
3662
3687
|
'doc': 'The tenant which contains the instance.'}),
|
|
3663
3688
|
)),
|
|
3664
3689
|
|
|
3690
|
+
('inet:service:app', {}, (
|
|
3691
|
+
|
|
3692
|
+
('name', ('str', {'lower': True, 'onespace': True}), {
|
|
3693
|
+
'alts': ('names',),
|
|
3694
|
+
'doc': 'The name of the platform specific application.'}),
|
|
3695
|
+
|
|
3696
|
+
('names', ('array', {'type': 'str',
|
|
3697
|
+
'typeopts': {'onespace': True, 'lower': True},
|
|
3698
|
+
'sorted': True, 'uniq': True}), {
|
|
3699
|
+
'doc': 'An array of alternate names for the application.'}),
|
|
3700
|
+
|
|
3701
|
+
('desc', ('str', {}), {
|
|
3702
|
+
'disp': {'hint': 'text'},
|
|
3703
|
+
'doc': 'A description of the platform specific application.'}),
|
|
3704
|
+
)),
|
|
3705
|
+
|
|
3665
3706
|
('inet:service:account', {}, (
|
|
3666
3707
|
|
|
3667
3708
|
('user', ('inet:user', {}), {
|
|
@@ -3802,6 +3843,9 @@ class InetModule(s_module.CoreModule):
|
|
|
3802
3843
|
('attachments', ('array', {'type': 'inet:service:message:attachment', 'uniq': True, 'sorted': True}), {
|
|
3803
3844
|
'doc': 'An array of files attached to the message.'}),
|
|
3804
3845
|
|
|
3846
|
+
('hashtags', ('array', {'type': 'inet:web:hashtag', 'uniq': True, 'sorted': True, 'split': ','}), {
|
|
3847
|
+
'doc': 'An array of hashtags mentioned within the message.'}),
|
|
3848
|
+
|
|
3805
3849
|
('place', ('geo:place', {}), {
|
|
3806
3850
|
'doc': 'The place that the message was sent from.'}),
|
|
3807
3851
|
|
|
@@ -3823,6 +3867,11 @@ class InetModule(s_module.CoreModule):
|
|
|
3823
3867
|
|
|
3824
3868
|
('type', ('inet:service:message:type:taxonomy', {}), {
|
|
3825
3869
|
'doc': 'The type of message.'}),
|
|
3870
|
+
|
|
3871
|
+
('mentions', ('array', {'type': 'ndef',
|
|
3872
|
+
'typeopts': {'forms': ('inet:service:account', 'inet:service:group')},
|
|
3873
|
+
'uniq': True, 'sorted': True}), {
|
|
3874
|
+
'doc': 'Contactable entities mentioned within the message.'}),
|
|
3826
3875
|
)),
|
|
3827
3876
|
|
|
3828
3877
|
('inet:service:message:link', {}, (
|
|
@@ -3863,6 +3912,9 @@ class InetModule(s_module.CoreModule):
|
|
|
3863
3912
|
|
|
3864
3913
|
('period', ('ival', {}), {
|
|
3865
3914
|
'doc': 'The time period where the channel was available.'}),
|
|
3915
|
+
|
|
3916
|
+
('topic', ('media:topic', {}), {
|
|
3917
|
+
'doc': 'The visible topic of the channel.'}),
|
|
3866
3918
|
)),
|
|
3867
3919
|
|
|
3868
3920
|
('inet:service:thread', {}, (
|
|
@@ -3926,6 +3978,9 @@ class InetModule(s_module.CoreModule):
|
|
|
3926
3978
|
|
|
3927
3979
|
('inet:service:access', {}, (
|
|
3928
3980
|
|
|
3981
|
+
('action', ('inet:service:access:action:taxonomy', {}), {
|
|
3982
|
+
'doc': 'The platform specific action which this access records.'}),
|
|
3983
|
+
|
|
3929
3984
|
('resource', ('inet:service:resource', {}), {
|
|
3930
3985
|
'doc': 'The resource which the account attempted to access.'}),
|
|
3931
3986
|
|
synapse/models/orgs.py
CHANGED
|
@@ -1241,7 +1241,6 @@ class OuModule(s_module.CoreModule):
|
|
|
1241
1241
|
)),
|
|
1242
1242
|
('ou:conference:event', {}, (
|
|
1243
1243
|
('conference', ('ou:conference', {}), {
|
|
1244
|
-
'ro': True,
|
|
1245
1244
|
'doc': 'The conference to which the event is associated.',
|
|
1246
1245
|
}),
|
|
1247
1246
|
('organizer', ('ps:contact', {}), {
|
synapse/models/person.py
CHANGED
|
@@ -490,13 +490,20 @@ class PsModule(s_module.CoreModule):
|
|
|
490
490
|
('crypto:address', ('crypto:currency:address', {}), {
|
|
491
491
|
'doc': 'A crypto currency address associated with the contact.'
|
|
492
492
|
}),
|
|
493
|
-
|
|
494
493
|
('lang', ('lang:language', {}), {
|
|
495
494
|
'alts': ('langs',),
|
|
496
495
|
'doc': 'The language specified for the contact.'}),
|
|
497
|
-
|
|
498
496
|
('langs', ('array', {'type': 'lang:language'}), {
|
|
499
497
|
'doc': 'An array of alternative languages specified for the contact.'}),
|
|
498
|
+
('banner', ('file:bytes', {}), {
|
|
499
|
+
'doc': 'The file representing the banner for the contact.'}),
|
|
500
|
+
('passwd', ('inet:passwd', {}), {
|
|
501
|
+
'doc': 'The current password for the contact.'}),
|
|
502
|
+
('website', ('inet:url', {}), {
|
|
503
|
+
'doc': 'A related URL specified by the contact (e.g., a personal or company web '
|
|
504
|
+
'page, blog, etc.).'}),
|
|
505
|
+
('websites', ('array', {'type': 'inet:url', 'uniq': True, 'sorted': True}), {
|
|
506
|
+
'doc': 'Alternative related URLs specified by the contact.'}),
|
|
500
507
|
)),
|
|
501
508
|
('ps:vitals', {}, (
|
|
502
509
|
('asof', ('time', {}), {
|
synapse/tests/test_cortex.py
CHANGED
|
@@ -152,12 +152,12 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
152
152
|
self.false((await core01.getCellInfo())['cell']['uplink'])
|
|
153
153
|
# Note: The following mirror may change when SYN-7659 is addressed and greater
|
|
154
154
|
# control over the topology update is available during the promotion process.
|
|
155
|
-
self.eq((await core00.getCellInfo())['cell']['mirror'], 'aha://
|
|
155
|
+
self.eq((await core00.getCellInfo())['cell']['mirror'], 'aha://root@cortex...')
|
|
156
156
|
self.none((await core01.getCellInfo())['cell']['mirror'])
|
|
157
157
|
|
|
158
158
|
mods00 = s_common.yamlload(core00.dirn, 'cell.mods.yaml')
|
|
159
159
|
mods01 = s_common.yamlload(core01.dirn, 'cell.mods.yaml')
|
|
160
|
-
self.eq(mods00, {'mirror': 'aha://
|
|
160
|
+
self.eq(mods00, {'mirror': 'aha://root@cortex...'})
|
|
161
161
|
self.eq(mods01, {'mirror': None})
|
|
162
162
|
|
|
163
163
|
await core00.nodes('[inet:ipv4=5.5.5.5]')
|
|
@@ -8367,7 +8367,7 @@ class CortexBasicTest(s_t_utils.SynTest):
|
|
|
8367
8367
|
dirn01 = s_common.genpath(dirn, 'cell01')
|
|
8368
8368
|
|
|
8369
8369
|
core00 = await base.enter_context(self.addSvcToAha(aha, '00.core', s_cortex.Cortex, dirn=dirn00))
|
|
8370
|
-
provinfo = {'mirror': '
|
|
8370
|
+
provinfo = {'mirror': 'core'}
|
|
8371
8371
|
core01 = await base.enter_context(self.addSvcToAha(aha, '01.core', s_cortex.Cortex, dirn=dirn01, provinfo=provinfo))
|
|
8372
8372
|
|
|
8373
8373
|
self.len(1, await core00.nodes('[inet:asn=0]'))
|