morango 0.6.11__py2.py3-none-any.whl → 0.8.6__py2.py3-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.
- morango/__init__.py +1 -6
- morango/api/serializers.py +3 -0
- morango/api/viewsets.py +38 -23
- morango/apps.py +1 -2
- morango/constants/settings.py +3 -0
- morango/constants/transfer_stages.py +1 -1
- morango/constants/transfer_statuses.py +1 -1
- morango/errors.py +4 -0
- morango/management/commands/cleanupsyncs.py +64 -14
- morango/migrations/0001_initial.py +0 -2
- morango/migrations/0001_squashed_0024_auto_20240129_1757.py +583 -0
- morango/migrations/0002_auto_20170511_0400.py +0 -2
- morango/migrations/0002_store_idx_morango_deserialize.py +21 -0
- morango/migrations/0003_auto_20170519_0543.py +0 -2
- morango/migrations/0004_auto_20170520_2112.py +0 -2
- morango/migrations/0005_auto_20170629_2139.py +0 -2
- morango/migrations/0006_instanceidmodel_system_id.py +0 -2
- morango/migrations/0007_auto_20171018_1615.py +0 -2
- morango/migrations/0008_auto_20171114_2217.py +0 -2
- morango/migrations/0009_auto_20171205_0252.py +0 -2
- morango/migrations/0010_auto_20171206_1615.py +0 -2
- morango/migrations/0011_sharedkey.py +0 -2
- morango/migrations/0012_auto_20180927_1658.py +0 -2
- morango/migrations/0013_auto_20190627_1513.py +0 -2
- morango/migrations/0014_syncsession_extra_fields.py +0 -2
- morango/migrations/0015_auto_20200508_2104.py +2 -3
- morango/migrations/0016_store_deserialization_error.py +2 -3
- morango/migrations/0017_store_last_transfer_session_id.py +1 -2
- morango/migrations/0018_auto_20210714_2216.py +2 -3
- morango/migrations/0019_auto_20220113_1807.py +2 -3
- morango/migrations/0020_postgres_fix_nullable.py +0 -2
- morango/migrations/0021_store_partition_index_create.py +0 -2
- morango/migrations/0022_rename_instance_fields.py +23 -0
- morango/migrations/0023_add_instance_id_fields.py +24 -0
- morango/migrations/0024_auto_20240129_1757.py +28 -0
- morango/models/__init__.py +0 -6
- morango/models/certificates.py +137 -28
- morango/models/core.py +48 -46
- morango/models/fields/crypto.py +20 -6
- morango/models/fields/uuids.py +2 -1
- morango/models/utils.py +5 -6
- morango/proquint.py +2 -3
- morango/registry.py +28 -49
- morango/sync/backends/base.py +34 -0
- morango/sync/backends/postgres.py +129 -0
- morango/sync/backends/utils.py +10 -11
- morango/sync/context.py +198 -13
- morango/sync/controller.py +33 -11
- morango/sync/operations.py +324 -251
- morango/sync/session.py +11 -0
- morango/sync/syncsession.py +78 -85
- morango/sync/utils.py +18 -0
- morango/urls.py +3 -3
- morango/utils.py +2 -3
- {morango-0.6.11.dist-info → morango-0.8.6.dist-info}/METADATA +29 -14
- morango-0.8.6.dist-info/RECORD +79 -0
- {morango-0.6.11.dist-info → morango-0.8.6.dist-info}/WHEEL +1 -1
- morango/models/morango_mptt.py +0 -33
- morango/settings.py +0 -115
- morango/wsgi.py +0 -33
- morango-0.6.11.dist-info/RECORD +0 -77
- {morango-0.6.11.dist-info → morango-0.8.6.dist-info/licenses}/AUTHORS.md +0 -0
- {morango-0.6.11.dist-info → morango-0.8.6.dist-info/licenses}/LICENSE +0 -0
- {morango-0.6.11.dist-info → morango-0.8.6.dist-info}/top_level.txt +0 -0
morango/__init__.py
CHANGED
morango/api/serializers.py
CHANGED
|
@@ -60,6 +60,9 @@ class NonceSerializer(serializers.ModelSerializer):
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
class SyncSessionSerializer(serializers.ModelSerializer):
|
|
63
|
+
client_instance = serializers.CharField(source='client_instance_json')
|
|
64
|
+
server_instance = serializers.CharField(source='server_instance_json')
|
|
65
|
+
|
|
63
66
|
class Meta:
|
|
64
67
|
model = SyncSession
|
|
65
68
|
fields = (
|
morango/api/viewsets.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import logging
|
|
2
3
|
import platform
|
|
3
4
|
import uuid
|
|
4
|
-
import logging
|
|
5
5
|
|
|
6
6
|
from django.core.exceptions import ValidationError
|
|
7
7
|
from django.utils import timezone
|
|
8
|
-
from ipware
|
|
8
|
+
from ipware import get_client_ip
|
|
9
9
|
from rest_framework import mixins
|
|
10
10
|
from rest_framework import pagination
|
|
11
11
|
from rest_framework import response
|
|
@@ -30,8 +30,8 @@ from morango.models.core import TransferSession
|
|
|
30
30
|
from morango.models.fields.crypto import SharedKey
|
|
31
31
|
from morango.sync.context import LocalSessionContext
|
|
32
32
|
from morango.sync.controller import SessionController
|
|
33
|
-
from morango.utils import CAPABILITIES
|
|
34
33
|
from morango.utils import _assert
|
|
34
|
+
from morango.utils import CAPABILITIES
|
|
35
35
|
from morango.utils import parse_capabilities_from_server_request
|
|
36
36
|
|
|
37
37
|
|
|
@@ -60,6 +60,11 @@ session_controller = SessionController.build()
|
|
|
60
60
|
session_controller.signals.connect(controller_signal_logger)
|
|
61
61
|
|
|
62
62
|
|
|
63
|
+
def get_ip(request):
|
|
64
|
+
client_ip, _ = get_client_ip(request)
|
|
65
|
+
return client_ip
|
|
66
|
+
|
|
67
|
+
|
|
63
68
|
class CertificateChainViewSet(viewsets.ViewSet):
|
|
64
69
|
permissions = (permissions.CertificatePushPermissions,)
|
|
65
70
|
|
|
@@ -236,7 +241,7 @@ class SyncSessionViewSet(
|
|
|
236
241
|
|
|
237
242
|
def create(self, request):
|
|
238
243
|
|
|
239
|
-
|
|
244
|
+
server_instance, _ = InstanceIDModel.get_or_create_current_instance()
|
|
240
245
|
|
|
241
246
|
# verify and save the certificate chain to our cert store
|
|
242
247
|
try:
|
|
@@ -287,6 +292,12 @@ class SyncSessionViewSet(
|
|
|
287
292
|
"Nonce is not valid", status=status.HTTP_403_FORBIDDEN
|
|
288
293
|
)
|
|
289
294
|
|
|
295
|
+
client_instance_json = request.data.get("instance")
|
|
296
|
+
client_instance_id = None
|
|
297
|
+
if client_instance_json:
|
|
298
|
+
client_instance = json.loads(client_instance_json)
|
|
299
|
+
client_instance_id = client_instance.get("id")
|
|
300
|
+
|
|
290
301
|
# build the data to be used for creation the syncsession
|
|
291
302
|
data = {
|
|
292
303
|
"id": request.data.get("id"),
|
|
@@ -301,9 +312,11 @@ class SyncSessionViewSet(
|
|
|
301
312
|
"connection_path": request.data.get("connection_path"),
|
|
302
313
|
"client_ip": get_ip(request) or "",
|
|
303
314
|
"server_ip": request.data.get("server_ip") or "",
|
|
304
|
-
"
|
|
305
|
-
"
|
|
306
|
-
|
|
315
|
+
"client_instance_id": client_instance_id,
|
|
316
|
+
"client_instance_json": client_instance_json,
|
|
317
|
+
"server_instance_id": server_instance.id,
|
|
318
|
+
"server_instance_json": json.dumps(
|
|
319
|
+
serializers.InstanceIDSerializer(server_instance).data
|
|
307
320
|
),
|
|
308
321
|
}
|
|
309
322
|
|
|
@@ -313,7 +326,7 @@ class SyncSessionViewSet(
|
|
|
313
326
|
|
|
314
327
|
resp_data = {
|
|
315
328
|
"signature": server_cert.sign(message),
|
|
316
|
-
"server_instance": data["
|
|
329
|
+
"server_instance": data["server_instance_json"],
|
|
317
330
|
}
|
|
318
331
|
|
|
319
332
|
return response.Response(resp_data, status=status.HTTP_201_CREATED)
|
|
@@ -368,8 +381,8 @@ class TransferSessionViewSet(
|
|
|
368
381
|
if scope_error_msg:
|
|
369
382
|
return response.Response(scope_error_msg, status=status.HTTP_403_FORBIDDEN)
|
|
370
383
|
|
|
371
|
-
context = LocalSessionContext(
|
|
372
|
-
request
|
|
384
|
+
context = LocalSessionContext.from_request(
|
|
385
|
+
request,
|
|
373
386
|
sync_session=syncsession,
|
|
374
387
|
sync_filter=requested_filter,
|
|
375
388
|
is_push=is_a_push,
|
|
@@ -416,8 +429,8 @@ class TransferSessionViewSet(
|
|
|
416
429
|
if update_stage is not None:
|
|
417
430
|
# if client is trying to update `transfer_stage`, then we use the controller to proceed
|
|
418
431
|
# to the stage, but wait for completion if both do not support async
|
|
419
|
-
context = LocalSessionContext(
|
|
420
|
-
request
|
|
432
|
+
context = LocalSessionContext.from_request(
|
|
433
|
+
request,
|
|
421
434
|
transfer_session=self.get_object(),
|
|
422
435
|
)
|
|
423
436
|
# special case for transferring, not to wait since it's a chunked process
|
|
@@ -431,8 +444,8 @@ class TransferSessionViewSet(
|
|
|
431
444
|
return super(TransferSessionViewSet, self).update(request, *args, **kwargs)
|
|
432
445
|
|
|
433
446
|
def perform_destroy(self, transfer_session):
|
|
434
|
-
context = LocalSessionContext(
|
|
435
|
-
|
|
447
|
+
context = LocalSessionContext.from_request(
|
|
448
|
+
self.request,
|
|
436
449
|
transfer_session=transfer_session,
|
|
437
450
|
)
|
|
438
451
|
if self.async_allowed():
|
|
@@ -482,8 +495,8 @@ class BufferViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
|
|
|
482
495
|
status=status.HTTP_403_FORBIDDEN,
|
|
483
496
|
)
|
|
484
497
|
|
|
485
|
-
context = LocalSessionContext(
|
|
486
|
-
request
|
|
498
|
+
context = LocalSessionContext.from_request(
|
|
499
|
+
request, transfer_session=transfer_session
|
|
487
500
|
)
|
|
488
501
|
result = session_controller.proceed_to(
|
|
489
502
|
transfer_stages.TRANSFERRING, context=context
|
|
@@ -509,13 +522,15 @@ class MorangoInfoViewSet(viewsets.ViewSet):
|
|
|
509
522
|
(id_model, _) = InstanceIDModel.get_or_create_current_instance()
|
|
510
523
|
# include custom instance info as well
|
|
511
524
|
m_info = id_model.instance_info.copy()
|
|
512
|
-
m_info.update(
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
525
|
+
m_info.update(
|
|
526
|
+
{
|
|
527
|
+
"instance_hash": id_model.get_proquint(),
|
|
528
|
+
"instance_id": id_model.id,
|
|
529
|
+
"system_os": platform.system(),
|
|
530
|
+
"version": morango.__version__,
|
|
531
|
+
"capabilities": CAPABILITIES,
|
|
532
|
+
}
|
|
533
|
+
)
|
|
519
534
|
return response.Response(m_info)
|
|
520
535
|
|
|
521
536
|
|
morango/apps.py
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from __future__ import unicode_literals
|
|
2
|
-
|
|
3
1
|
from django.apps import AppConfig
|
|
4
2
|
|
|
5
3
|
from morango.registry import session_middleware
|
|
@@ -9,6 +7,7 @@ from morango.registry import syncable_models
|
|
|
9
7
|
class MorangoConfig(AppConfig):
|
|
10
8
|
name = "morango"
|
|
11
9
|
verbose_name = "Morango"
|
|
10
|
+
default_auto_field = "django.db.models.AutoField"
|
|
12
11
|
|
|
13
12
|
def ready(self):
|
|
14
13
|
from morango.models.signals import add_to_deleted_models # noqa: F401
|
morango/constants/settings.py
CHANGED
|
@@ -23,7 +23,9 @@ MORANGO_QUEUE_OPERATIONS = (
|
|
|
23
23
|
)
|
|
24
24
|
MORANGO_TRANSFERRING_OPERATIONS = (
|
|
25
25
|
"morango.sync.operations:PullProducerOperation",
|
|
26
|
+
"morango.sync.operations:PushProducerOperation",
|
|
26
27
|
"morango.sync.operations:PushReceiverOperation",
|
|
28
|
+
"morango.sync.operations:PullReceiverOperation",
|
|
27
29
|
"morango.sync.operations:NetworkPushTransferOperation",
|
|
28
30
|
"morango.sync.operations:NetworkPullTransferOperation",
|
|
29
31
|
)
|
|
@@ -43,3 +45,4 @@ MORANGO_CLEANUP_OPERATIONS = (
|
|
|
43
45
|
"morango.sync.operations:CleanupOperation",
|
|
44
46
|
"morango.sync.operations:NetworkCleanupOperation",
|
|
45
47
|
)
|
|
48
|
+
MORANGO_TEST_POSTGRESQL = False
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
This module contains constants representing the possible stages of a transfer session.
|
|
3
3
|
"""
|
|
4
|
-
from django.utils.translation import
|
|
4
|
+
from django.utils.translation import gettext_lazy as _
|
|
5
5
|
|
|
6
6
|
INITIALIZING = "initializing"
|
|
7
7
|
SERIALIZING = "serializing"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
This module contains constants representing the possible statuses of a transfer session stage.
|
|
3
3
|
"""
|
|
4
|
-
from django.utils.translation import
|
|
4
|
+
from django.utils.translation import gettext_lazy as _
|
|
5
5
|
|
|
6
6
|
PENDING = "pending"
|
|
7
7
|
STARTED = "started"
|
morango/errors.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
import logging
|
|
3
|
+
import uuid
|
|
3
4
|
|
|
4
5
|
from django.core.management.base import BaseCommand
|
|
5
6
|
from django.db import transaction
|
|
@@ -29,6 +30,36 @@ class Command(BaseCommand):
|
|
|
29
30
|
default=6,
|
|
30
31
|
help="Number of hours of inactivity after which a session should be considered stale",
|
|
31
32
|
)
|
|
33
|
+
parser.add_argument(
|
|
34
|
+
"--client-instance-id",
|
|
35
|
+
type=uuid.UUID,
|
|
36
|
+
default=None,
|
|
37
|
+
help="Filters the SyncSession models to those with matching 'client_instance_id'",
|
|
38
|
+
)
|
|
39
|
+
parser.add_argument(
|
|
40
|
+
"--server-instance-id",
|
|
41
|
+
type=uuid.UUID,
|
|
42
|
+
default=None,
|
|
43
|
+
help="Filters the SyncSession models to those with matching 'server_instance_id'",
|
|
44
|
+
)
|
|
45
|
+
parser.add_argument(
|
|
46
|
+
"--sync-filter",
|
|
47
|
+
type=str,
|
|
48
|
+
default=None,
|
|
49
|
+
help="Filters the TransferSession models to those with 'filters' starting with 'sync_filter'",
|
|
50
|
+
)
|
|
51
|
+
parser.add_argument(
|
|
52
|
+
"--push",
|
|
53
|
+
type=bool,
|
|
54
|
+
default=None,
|
|
55
|
+
help="Filters the TransferSession models to those with 'push' set to True",
|
|
56
|
+
)
|
|
57
|
+
parser.add_argument(
|
|
58
|
+
"--pull",
|
|
59
|
+
type=bool,
|
|
60
|
+
default=None,
|
|
61
|
+
help="Filters the TransferSession models to those with 'push' set to False",
|
|
62
|
+
)
|
|
32
63
|
|
|
33
64
|
def handle(self, *args, **options):
|
|
34
65
|
|
|
@@ -37,10 +68,17 @@ class Command(BaseCommand):
|
|
|
37
68
|
|
|
38
69
|
sync_sessions = SyncSession.objects.filter(active=True)
|
|
39
70
|
|
|
40
|
-
# if ids arg was passed, filter down sessions to only those IDs
|
|
71
|
+
# if ids arg was passed, filter down sessions to only those IDs
|
|
72
|
+
# if included by expiration filter
|
|
41
73
|
if options["ids"]:
|
|
42
74
|
sync_sessions = sync_sessions.filter(id__in=options["ids"])
|
|
43
75
|
|
|
76
|
+
if options["client_instance_id"]:
|
|
77
|
+
sync_sessions = sync_sessions.filter(client_instance_id=options["client_instance_id"])
|
|
78
|
+
|
|
79
|
+
if options["server_instance_id"]:
|
|
80
|
+
sync_sessions = sync_sessions.filter(server_instance_id=options["server_instance_id"])
|
|
81
|
+
|
|
44
82
|
# retrieve all sessions still marked as active but with no activity since the cutoff
|
|
45
83
|
transfer_sessions = TransferSession.objects.filter(
|
|
46
84
|
sync_session_id__in=sync_sessions.values("id"),
|
|
@@ -48,11 +86,19 @@ class Command(BaseCommand):
|
|
|
48
86
|
last_activity_timestamp__lt=cutoff,
|
|
49
87
|
)
|
|
50
88
|
|
|
89
|
+
if options["sync_filter"]:
|
|
90
|
+
transfer_sessions = transfer_sessions.filter(filter__startswith=options["sync_filter"])
|
|
91
|
+
|
|
92
|
+
if options["push"] and not options["pull"]:
|
|
93
|
+
transfer_sessions = transfer_sessions.filter(push=True)
|
|
94
|
+
|
|
95
|
+
if options["pull"] and not options["push"]:
|
|
96
|
+
transfer_sessions = transfer_sessions.filter(push=False)
|
|
97
|
+
|
|
51
98
|
transfer_count = transfer_sessions.count()
|
|
52
99
|
|
|
53
100
|
# loop over the stale sessions one by one to close them out
|
|
54
|
-
for i in
|
|
55
|
-
transfer_session = transfer_sessions[0]
|
|
101
|
+
for i, transfer_session in enumerate(transfer_sessions):
|
|
56
102
|
logger.info(
|
|
57
103
|
"TransferSession {} of {}: deleting {} Buffers and {} RMC Buffers...".format(
|
|
58
104
|
i + 1,
|
|
@@ -68,17 +114,21 @@ class Command(BaseCommand):
|
|
|
68
114
|
transfer_session.active = False
|
|
69
115
|
transfer_session.save()
|
|
70
116
|
|
|
117
|
+
# in order to close a sync session, it must have no active transfer sessions
|
|
118
|
+
# and must have no activity since the cutoff
|
|
119
|
+
sync_sessions = sync_sessions.filter(
|
|
120
|
+
last_activity_timestamp__lt=cutoff,
|
|
121
|
+
).exclude(
|
|
122
|
+
transfersession__active=True,
|
|
123
|
+
)
|
|
71
124
|
sync_count = sync_sessions.count()
|
|
72
125
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
"Closing SyncSession {} of {}".format(
|
|
79
|
-
i + 1,
|
|
80
|
-
sync_count,
|
|
81
|
-
)
|
|
126
|
+
for i, sync_session in enumerate(sync_sessions):
|
|
127
|
+
logger.info(
|
|
128
|
+
"Closing SyncSession {} of {}".format(
|
|
129
|
+
i + 1,
|
|
130
|
+
sync_count,
|
|
82
131
|
)
|
|
83
|
-
|
|
84
|
-
|
|
132
|
+
)
|
|
133
|
+
sync_session.active = False
|
|
134
|
+
sync_session.save()
|