diff --git a/kolibri/core/auth/models.py b/kolibri/core/auth/models.py index 2ccb4e7857..2686e83a12 100644 --- a/kolibri/core/auth/models.py +++ b/kolibri/core/auth/models.py @@ -1498,7 +1498,20 @@ def ensure_dataset(self, *args, **kwargs): def infer_dataset(self, *args, **kwargs): # if we don't yet have a dataset, create a new one for this facility if not self.dataset_id: - self.dataset = FacilityDataset.objects.create() + from kolibri.core.device.models import DEFAULT_DEMOGRAPHIC_FIELDS_KEY + + kwargs = {} + + default_demographic_fields = get_device_setting( + DEFAULT_DEMOGRAPHIC_FIELDS_KEY + ) + + if default_demographic_fields: + kwargs["extra_fields"] = { + DEMOGRAPHIC_FIELDS_KEY: default_demographic_fields + } + + self.dataset = FacilityDataset.objects.create(**kwargs) return self.dataset_id def get_classrooms(self): diff --git a/kolibri/core/device/migrations/0021_default_demographic_fields.py b/kolibri/core/device/migrations/0021_default_demographic_fields.py new file mode 100644 index 0000000000..98a4a74fa9 --- /dev/null +++ b/kolibri/core/device/migrations/0021_default_demographic_fields.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.29 on 2024-03-28 15:35 +from __future__ import unicode_literals + +from django.db import migrations + +import kolibri.core.auth.constants.demographics +import kolibri.core.fields +import kolibri.core.utils.validators + + +class Migration(migrations.Migration): + + dependencies = [ + ("device", "0020_fix_learner_device_status_choices"), + ] + + operations = [ + migrations.AlterField( + model_name="devicesettings", + name="extra_settings", + field=kolibri.core.fields.JSONField( + default={ + "allow_download_on_metered_connection": False, + "allow_learner_download_resources": False, + "enable_automatic_download": True, + "limit_for_autodownload": 0, + "set_limit_for_autodownload": False, + }, + validators=[ + kolibri.core.utils.validators.JSON_Schema_Validator( + { + "properties": { + "allow_download_on_metered_connection": { + "type": "boolean" + }, + "allow_learner_download_resources": { + "optional": True, + "type": "boolean", + }, + "default_demographic_field_schema": { + "items": { + "properties": { + "description": {"type": "string"}, + "enumValues": { + "items": { + "properties": { + "defaultLabel": { + "type": "string" + }, + "translations": { + "items": { + "properties": { + "language": { + "enum": [ + "ar", + "bg-bg", + "bn-bd", + "de", + "el", + "en", + "es-419", + "es-es", + "fa", + "ff-cm", + "fr-fr", + "gu-in", + "ha", + "hi-in", + "ht", + "id", + "it", + "ka", + "km", + "ko", + "mr", + "my", + "nyn", + "pt-br", + "pt-mz", + "sw-tz", + "te", + "uk", + "ur-pk", + "vi", + "yo", + "zh-hans", + ], + "type": "string", + }, + "message": { + "type": "string" + }, + }, + "type": "object", + }, + "optional": True, + "type": "array", + }, + "value": {"type": "string"}, + }, + "type": "object", + }, + "type": "array", + }, + "id": {"type": "string"}, + "translations": { + "items": { + "properties": { + "language": { + "enum": [ + "ar", + "bg-bg", + "bn-bd", + "de", + "el", + "en", + "es-419", + "es-es", + "fa", + "ff-cm", + "fr-fr", + "gu-in", + "ha", + "hi-in", + "ht", + "id", + "it", + "ka", + "km", + "ko", + "mr", + "my", + "nyn", + "pt-br", + "pt-mz", + "sw-tz", + "te", + "uk", + "ur-pk", + "vi", + "yo", + "zh-hans", + ], + "type": "string", + }, + "message": {"type": "string"}, + }, + "type": "object", + }, + "optional": True, + "type": "array", + }, + }, + "type": "object", + }, + "optional": True, + "type": "array", + }, + "enable_automatic_download": {"type": "boolean"}, + "limit_for_autodownload": { + "optional": True, + "type": "integer", + }, + "set_limit_for_autodownload": { + "optional": True, + "type": "boolean", + }, + }, + "required": [ + "allow_download_on_metered_connection", + "enable_automatic_download", + ], + "type": "object", + } + ), + kolibri.core.auth.constants.demographics.UniqueIdsValidator( + "default_demographic_field_schema" + ), + kolibri.core.auth.constants.demographics.DescriptionTranslationValidator( + "default_demographic_field_schema" + ), + kolibri.core.auth.constants.demographics.EnumValuesValidator( + "default_demographic_field_schema" + ), + kolibri.core.auth.constants.demographics.LabelTranslationValidator( + "default_demographic_field_schema" + ), + ], + ), + ), + ] diff --git a/kolibri/core/device/models.py b/kolibri/core/device/models.py index 07b25c0443..6d415e889a 100644 --- a/kolibri/core/device/models.py +++ b/kolibri/core/device/models.py @@ -13,6 +13,11 @@ from .utils import LANDING_PAGE_LEARN from .utils import LANDING_PAGE_SIGN_IN from kolibri.core.auth.constants import role_kinds +from kolibri.core.auth.constants.demographics import custom_demographics_schema +from kolibri.core.auth.constants.demographics import DescriptionTranslationValidator +from kolibri.core.auth.constants.demographics import EnumValuesValidator +from kolibri.core.auth.constants.demographics import LabelTranslationValidator +from kolibri.core.auth.constants.demographics import UniqueIdsValidator from kolibri.core.auth.models import AbstractFacilityDataModel from kolibri.core.auth.models import Facility from kolibri.core.auth.models import FacilityUser @@ -88,6 +93,9 @@ def app_is_enabled(): return interface.enabled +DEFAULT_DEMOGRAPHIC_FIELDS_KEY = "default_demographic_field_schema" + + # '"optional":True' is obsolete but needed while we keep using an # old json_schema_validator version compatible with python 2.7 extra_settings_schema = { @@ -98,6 +106,7 @@ def app_is_enabled(): "allow_learner_download_resources": {"type": "boolean", "optional": True}, "set_limit_for_autodownload": {"type": "boolean", "optional": True}, "limit_for_autodownload": {"type": "integer", "optional": True}, + DEFAULT_DEMOGRAPHIC_FIELDS_KEY: custom_demographics_schema, }, "required": [ "allow_download_on_metered_connection", @@ -155,7 +164,13 @@ class DeviceSettings(models.Model): extra_settings = JSONField( null=False, - validators=[JSON_Schema_Validator(extra_settings_schema)], + validators=[ + JSON_Schema_Validator(extra_settings_schema), + UniqueIdsValidator(DEFAULT_DEMOGRAPHIC_FIELDS_KEY), + DescriptionTranslationValidator(DEFAULT_DEMOGRAPHIC_FIELDS_KEY), + EnumValuesValidator(DEFAULT_DEMOGRAPHIC_FIELDS_KEY), + LabelTranslationValidator(DEFAULT_DEMOGRAPHIC_FIELDS_KEY), + ], default=extra_settings_default_values, )