-
Notifications
You must be signed in to change notification settings - Fork 716
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Single-user sync exams, migrate to hooks, and upgrade morango to 0.6.2
- Loading branch information
Showing
13 changed files
with
414 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from kolibri.plugins.hooks import define_hook | ||
from kolibri.plugins.hooks import KolibriHook | ||
|
||
|
||
@define_hook | ||
class FacilityDataSyncHook(KolibriHook): | ||
""" | ||
A hook to allow plugins to register callbacks for sync events they're interested in. | ||
""" | ||
|
||
def pre_transfer( | ||
self, | ||
dataset_id, | ||
local_is_single_user, | ||
remote_is_single_user, | ||
single_user_id, | ||
context, | ||
): | ||
pass | ||
|
||
def post_transfer( | ||
self, | ||
dataset_id, | ||
local_is_single_user, | ||
remote_is_single_user, | ||
single_user_id, | ||
context, | ||
): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import json | ||
|
||
from morango.sync.context import LocalSessionContext | ||
|
||
from kolibri.core.auth.constants.morango_sync import ScopeDefinitions | ||
from kolibri.core.auth.hooks import FacilityDataSyncHook | ||
|
||
|
||
def _get_our_cert(context): | ||
ss = context.sync_session | ||
return ss.server_certificate if ss.is_server else ss.client_certificate | ||
|
||
|
||
def _get_their_cert(context): | ||
ss = context.sync_session | ||
return ss.client_certificate if ss.is_server else ss.server_certificate | ||
|
||
|
||
def _this_side_using_single_user_cert(context): | ||
return _get_our_cert(context).scope_definition_id == ScopeDefinitions.SINGLE_USER | ||
|
||
|
||
def _other_side_using_single_user_cert(context): | ||
return _get_their_cert(context).scope_definition_id == ScopeDefinitions.SINGLE_USER | ||
|
||
|
||
def _get_user_id_for_single_user_sync(context): | ||
if _other_side_using_single_user_cert(context): | ||
cert = _get_their_cert(context) | ||
elif _this_side_using_single_user_cert(context): | ||
cert = _get_our_cert(context) | ||
else: | ||
return None | ||
return json.loads(cert.scope_params)["user_id"] | ||
|
||
|
||
def _extract_kwargs_from_context(context): | ||
return { | ||
"dataset_id": _get_our_cert(context).get_root().id, | ||
"local_is_single_user": _this_side_using_single_user_cert(context), | ||
"remote_is_single_user": _other_side_using_single_user_cert(context), | ||
"single_user_id": _get_user_id_for_single_user_sync(context), | ||
"context": context, | ||
} | ||
|
||
|
||
def _pre_transfer_handler(context): | ||
assert context is not None | ||
|
||
kwargs = _extract_kwargs_from_context(context) | ||
|
||
if isinstance(context, LocalSessionContext): | ||
for hook in FacilityDataSyncHook.registered_hooks: | ||
hook.pre_transfer(**kwargs) | ||
|
||
|
||
def _post_transfer_handler(context): | ||
assert context is not None | ||
|
||
kwargs = _extract_kwargs_from_context(context) | ||
|
||
if isinstance(context, LocalSessionContext): | ||
for hook in FacilityDataSyncHook.registered_hooks: | ||
hook.post_transfer(**kwargs) | ||
|
||
|
||
def register_sync_event_handlers(session_controller): | ||
session_controller.signals.initializing.completed.connect(_pre_transfer_handler) | ||
session_controller.signals.cleanup.completed.connect(_post_transfer_handler) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
from .single_user_assignment_utils import ( | ||
update_assignments_from_individual_syncable_exams, | ||
) | ||
from .single_user_assignment_utils import ( | ||
update_individual_syncable_exams_from_assignments, | ||
) | ||
from kolibri.core.auth.hooks import FacilityDataSyncHook | ||
from kolibri.plugins.hooks import register_hook | ||
|
||
|
||
@register_hook | ||
class SingleUserLessonSyncHook(FacilityDataSyncHook): | ||
def pre_transfer( | ||
self, | ||
dataset_id, | ||
local_is_single_user, | ||
remote_is_single_user, | ||
single_user_id, | ||
context, | ||
): | ||
# if we're about to send data to a single-user device, prep the syncable exam assignments | ||
if context.is_producer and remote_is_single_user: | ||
update_individual_syncable_exams_from_assignments(single_user_id) | ||
|
||
def post_transfer( | ||
self, | ||
dataset_id, | ||
local_is_single_user, | ||
remote_is_single_user, | ||
single_user_id, | ||
context, | ||
): | ||
# if we've just received data on a single-user device, update the exams and assignments | ||
if context.is_receiver and local_is_single_user: | ||
update_assignments_from_individual_syncable_exams(single_user_id) |
69 changes: 69 additions & 0 deletions
69
kolibri/core/exams/migrations/0005_individualsyncableexam.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
# -*- coding: utf-8 -*- | ||
# Generated by Django 1.11.29 on 2021-07-27 03:17 | ||
from __future__ import unicode_literals | ||
|
||
import django.db.models.deletion | ||
import morango.models.fields.uuids | ||
from django.conf import settings | ||
from django.db import migrations | ||
from django.db import models | ||
|
||
import kolibri.core.fields | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
("kolibriauth", "0019_collection_no_mptt"), | ||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||
("exams", "0004_exam_add_dates_opened_created_and_archived"), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name="IndividualSyncableExam", | ||
fields=[ | ||
( | ||
"id", | ||
morango.models.fields.uuids.UUIDField( | ||
editable=False, primary_key=True, serialize=False | ||
), | ||
), | ||
( | ||
"_morango_dirty_bit", | ||
models.BooleanField(default=True, editable=False), | ||
), | ||
("_morango_source_id", models.CharField(editable=False, max_length=96)), | ||
( | ||
"_morango_partition", | ||
models.CharField(editable=False, max_length=128), | ||
), | ||
("exam_id", models.UUIDField()), | ||
("serialized_exam", kolibri.core.fields.JSONField()), | ||
( | ||
"collection", | ||
models.ForeignKey( | ||
on_delete=django.db.models.deletion.CASCADE, | ||
to="kolibriauth.Collection", | ||
), | ||
), | ||
( | ||
"dataset", | ||
models.ForeignKey( | ||
on_delete=django.db.models.deletion.CASCADE, | ||
to="kolibriauth.FacilityDataset", | ||
), | ||
), | ||
( | ||
"user", | ||
models.ForeignKey( | ||
on_delete=django.db.models.deletion.CASCADE, | ||
to=settings.AUTH_USER_MODEL, | ||
), | ||
), | ||
], | ||
options={ | ||
"abstract": False, | ||
}, | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.