Skip to content
Snippets Groups Projects
Commit fd5ab904 authored by Lennard Strohmeyer's avatar Lennard Strohmeyer :penguin:
Browse files

updated documentation, made migration for very old schemas more robust

parent b759195e
No related branches found
No related tags found
No related merge requests found
Pipeline #1648342 passed
# Provider Schema
A provider schema is a JSON file that contains information regarding the xAPI Verbs and Objects transmitted by the provider system. For instance, a Moodle system can transmit various verbs such as "accessed" or "viewed." Polaris requires knowledge of the structure and a list of these verbs in order to request users' consent.
Furthermore, the schema includes descriptions and textual information explaining the purpose of the data collection. This allows the administrator to make updates to the schema within the administration interface of Polaris.
A provider schema is a JSON file that contains information regarding the xAPI Verbs and Objects transmitted by the provider system.
For instance, a Moodle system may transmit various verbs such as "accessed" or "viewed." Polaris requires knowledge of the structure and a list of these verbs in order to verify users' consent.
## Structure
The provider schema is documented within a JSON file and can be uploaded via the administrative interface of Polaris. This schema adheres to a JSON schema, which is accessible in the rights engine repository at `src/static/provider_schema.schema.json`. In the subsequent section, we will guide you through a detailed, step-by-step explanation of the JSON file's structure.
......@@ -14,71 +13,47 @@ The following example contains a schema that only contains the relevant informat
"id": "moodle-0",
"name": "Moodle",
"description": "Open-source learning management system",
"groups": [
"verbs": [
...
]
}
```
The "id" should be the unique id of the provider system. The "id" should be the same if you like to update the schema. The "Name" and "Description" are presented to users as an explanation of the data collection carried out by this service.
The "id" should be the unique id of the provider system and you have to use the same "id" if you update the schema. The "Name" and "Description" fields may be presented to users as an explanation of the data collection carried out by this service.
### Minimal example with verbs
The following example contains a schema with a single group of xAPI Verbs. Each schema should contain at least one group of xAPI verbs
The following example contains a schema with a single xAPI Verb. Each schema should contain at least one xAPI verb.
```json
{
"id":"moodle-0",
"name":"Moodle",
"description":"Open-source learning management system",
"groups":[
"verbs":[
{
"id":"default_group",
"label":"Default group",
"description":"default",
"showVerbDetails":true,
"purposeOfCollection":"Lorem Ipsum",
"verbs":[
{
"id":"http://moodle.example.com/expapi/verbs/completed",
"label":"Completed",
"description":"Completed",
"defaultConsent":true
}
]
"id":"http://moodle.example.com/expapi/verbs/completed",
"label":"Completed",
"description":"Completed",
"defaultConsent":true
}
]
}
```
The schema provided above represents the minimal practical example. It includes a single group labeled "Default group" and a single verb identified by the ID `http://moodle.example.com/expapi/verbs/completed`. It's essential for the "id" field to correspond to the ID used in the xAPI statement. When a user consents to data collection, Polaris specifically collects verbs with the ID `http://moodle.example.com/expapi/verbs/completed`. Any xAPI verbs not included in the schema will not be collected under any circumstances.
The schema provided above represents the minimal practical example. It includes a verb identified by the ID `http://moodle.example.com/expapi/verbs/completed`. It's essential for the "id" field to correspond to the ID used in the xAPI statement. When a user consents to data collection, Polaris specifically collects verbs with the ID `http://moodle.example.com/expapi/verbs/completed`. Any xAPI verbs not included in a schema will not be collected under any circumstances.
You have the flexibility to update the schema whenever it becomes necessary to add new verbs. However, it's important to note that when new verbs and objects are introduced, users will need to provide their consent once again.
### Groups
Now, let's delve deeper into the group configuration options. A group serves as a straightforward means of organizing xAPI settings. The advantage of this grouping is that users can provide consent for all associated verbs with a single toggle within the Polaris user interface.
```json
{
"id":"default_group",
"label":"Default group",
"description":"default",
"showVerbDetails":true,
"purposeOfCollection":"Lorem Ipsum",
"verbs":[
...
]
}
```
The "id" property serves as a simple and unique identifier for the group within the provider. The "label" functions as the headline of the group in the user consent view within the user interface. The "description" property, positioned beneath the label, provides an informative description of the group's purpose. Ideally, both the group label and description should offer a clear and enlightening explanation of the data collection's intent.
The "purposeOfCollection" property serves a similar function but allows for additional information to be included for the data disclosure report. This text is automatically incorporated into a PDF report that users can generate in Polaris.
While not directly included in the provider schema, it is important to understand the structure in which users can consent to data collection.
A group, including an arbitrary list of verbs, serves as a straightforward means of organizing consent settings and corresponding xAPI verbs.
The advantage of this grouping is that users can provide consent for all associated verbs of a group with a single toggle within the Polaris user interface.
The "showVerbDetails" property enables the option to toggle between displaying verbs in detail for the user or allowing the user to consent to data collection for the entire group. This feature provides flexibility in how users can interact with and provide consent for data collection.
Groups can be created in the administrative interface of POLARIS and will be migrated to new schema versions whenever a schema is updated.
### Verbs
Going one level deeper, we have the ability to configure individual xAPI verbs. In the subsequent sections, we will provide an explanation of the available options for each xAPI verb.
Back in the provider schema we have the ability to configure individual xAPI verbs. In the subsequent sections, we will provide an explanation of the available options for each xAPI verb.
```json
{
......@@ -162,14 +137,14 @@ The "label" and "defaultConsent" properties within the object configuration func
The "definition" section within the configuration should be copied from a sample statement and must match the definition part of the object in the xAPI statement generated by the user. If the definition in the configuration does not correspond to the definition in the user's xAPI statement, Polaris will reject the statement.
### Essential verbs
Essential verbs are verbs that are always collected. The user can not disagree to this data collection, however Polaris will inform the user about the collection. The essential verbs are definited in the root node of the provider schema configuration.
Essential verbs are verbs that are always collected. The user can not disagree to this data collection, however Polaris will inform the user about the collection.
```json
{
"id": "h5p-0",
"name": "H5P",
"description": "Open-source content collaboration framework",
"groups": [
"verbs": [
...
],
"essentialVerbs": [
......@@ -184,17 +159,18 @@ Essential verbs are verbs that are always collected. The user can not disagree t
}
```
The configuration of the verbs is identical to that of other verbs within the schema. You can also restrict the verbs to specific verbs. That allows the essential data collection for example for specific objects using the id-based filtering approach.
The configuration of the verbs is identical to that of other verbs within the schema. You can also restrict the verbs to specific verbs, which allows collection of essential data for specific objects using the id-based filtering approach, for example.
### Additional LRS
Additional LRS can be supplied to forward incoming xAPI statements for the given provider to further LRS, in addition to the global LRS set for the application. Statements are forwarded without further filtering.
Authorization with the additional LRS can be done through bearer tokens, passwords or API keys.
```json
{
"id": "h5p-0",
"name": "H5P",
"description": "Open-source content collaboration framework",
"groups": [
"verbs": [
...
],
"essentialVerbs": [
......@@ -203,20 +179,21 @@ Additional LRS can be supplied to forward incoming xAPI statements for the given
"additionalLrs": [
{
"url": "https://other-lrs.example.com/xapi/statements",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzMyNzE5..."
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzMyNzE5...",
"token_type": "Bearer"
}
]
}
```
## Validate Schema
It is possible to validate the schema againts the json schema from the repository of the rights engine (`src/static/provider_schema.schema.json`). You can use multiple online tools like https://www.jsonschemavalidator.net/ to validate the schema before uploading it to Polaris.
It is possible to validate the schema against the json schema from the repository of the rights engine (`src/static/provider_schema.schema.json`). You can use online tools like https://www.jsonschemavalidator.net/ or offline tools like python-jsonschema to validate the schema before uploading it to Polaris.
## Update Schema
The provider schema can be updated at any time, offering the flexibility to make changes such as adding or removing groups, verbs, and objects. You can also modify the status of verbs, shifting them between "essential" and "optional." However, it is advisable to avoid including the same verb in both the "essential" and "optional" sections within the same schema version to prevent confusion.
The provider schema can be updated at any time, offering the flexibility to make changes such as adding verbs and objects. You can also modify the status of verbs, shifting them between "essential" and "optional."
Polaris has the capability to generate a comparison between different versions of the schema, making it easier for users to review the changes made. This streamlined process ensures that users only need to focus on the parts of the schema that have been altered, enhancing the efficiency of schema updates and user consent management.
Polaris has the capability to generate a comparison between different versions of the schema, making it easier for users to review the changes made. This streamlined process ensures that users only need to focus on the parts of the schema that have been altered, enhancing the efficiency of schema updates and consent group management.
To update the schema, you can upload a new JSON file with the same identifier as an existing provider. This identifier serves as a reference to the specific provider, allowing you to replace the previous schema with the updated one, ensuring continuity in your data collection and consent management process.
......@@ -238,93 +215,83 @@ You have the option to retain the existing schema, translate specific properties
"id": "moodle-0",
"name": "Moodle",
"description": "Open-source learning management system",
"groups": [
"verbs": [
{
"id": "default_group",
"label": "Default group",
"description": "default",
"showVerbDetails": true,
"purposeOfCollection": "Lorem Ipsum",
"verbs": [
"id": "http://moodle.example.com/expapi/verbs/completed",
"label": "Completed",
"description": "Completed",
"defaultConsent": true,
"objects": [
{
"id": "http://moodle.example.com/expapi/verbs/completed",
"label": "Completed",
"description": "Completed",
"id": "http://moodle.example.com/expapi/activity/programming-course-python",
"label": "Python Programming Course",
"defaultConsent": true,
"objects": [
{
"id": "http://moodle.example.com/expapi/activity/programming-course-python",
"label": "Python Programming Course",
"defaultConsent": true,
"matching": "definitionType",
"definition": {
"type": "http://moodle.example.com/expapi/activity/programming-course-python",
"name": {
"enUS": "Python Programming Course"
}
}
},
{
"id": "http://moodle.example.com/expapi/activity/foreign-language-course",
"label": "Foreign language course",
"defaultConsent": true,
"matching": "definitionType",
"definition": {
"type": "http://moodle.example.com/expapi/activity/foreign-language-course",
"name": {
"enUS": "Foreign language course"
}
}
}
]
},
{
"id": "http://moodle.example.com/expapi/verbs/started",
"label": "Started",
"description": "Started",
"defaultConsent": false,
"matching": "definitionType",
"objects": []
},
{
"id": "http://moodle.example.com/expapi/verbs/paused",
"label": "Paused",
"description": "paused",
"defaultConsent": false,
"matching": "definitionType",
"objects": []
"definition": {
"type": "http://moodle.example.com/expapi/activity/programming-course-python",
"name": {
"enUS": "Python Programming Course"
}
}
},
{
"id": "http://moodle.example.com/expapi/verbs/created",
"label": "Created",
"description": "Created",
"defaultConsent": false,
"id": "http://moodle.example.com/expapi/activity/foreign-language-course",
"label": "Foreign language course",
"defaultConsent": true,
"matching": "definitionType",
"objects": []
},
"definition": {
"type": "http://moodle.example.com/expapi/activity/foreign-language-course",
"name": {
"enUS": "Foreign language course"
}
}
}
]
},
{
"id": "http://moodle.example.com/expapi/verbs/started",
"label": "Started",
"description": "Started",
"defaultConsent": false,
"matching": "definitionType",
"objects": []
},
{
"id": "http://moodle.example.com/expapi/verbs/paused",
"label": "Paused",
"description": "paused",
"defaultConsent": false,
"matching": "definitionType",
"objects": []
},
{
"id": "http://moodle.example.com/expapi/verbs/created",
"label": "Created",
"description": "Created",
"defaultConsent": false,
"matching": "definitionType",
"objects": []
},
{
"id": "http://moodle.example.com/expapi/verbs/answered",
"label": "Answered",
"description": "Answered",
"defaultConsent": true,
"matching": "definitionType",
"objects": [
{
"id": "http://moodle.example.com/expapi/verbs/answered",
"label": "Answered",
"description": "Answered",
"id": "http://moodle.example.com/expapi/activity/poll-preferred-course-level",
"label": "Poll: Preferred course level",
"defaultConsent": true,
"matching": "definitionType",
"objects": [
{
"id": "http://moodle.example.com/expapi/activity/poll-preferred-course-level",
"label": "Poll: Preferred course level",
"defaultConsent": true,
"matching": "definitionType",
"definition": {
"type": "http://moodle.example.com/expapi/activity/poll-preferred-course-level",
"name": {
"enUS": "Poll: Preferred course level"
}
}
"definition": {
"type": "http://moodle.example.com/expapi/activity/poll-preferred-course-level",
"name": {
"enUS": "Poll: Preferred course level"
}
]
}
}
],
"isDefault": true
]
}
],
"essentialVerbs": [],
......
......@@ -259,7 +259,7 @@ class CreateProviderConsentView(APIView):
providerModel = Provider.objects.get(
definition_id=provider_schema["id"]
) # maybe TODO: match via name, not definition_id, iff definition_id can change each definition
)
providerModel.description = provider_schema["description"]
providerModel.save()
except OSError:
......
......@@ -47,16 +47,18 @@ def migrate_schema_to_objects(apps, schema_editor):
allow_anonymized_collection = verb_data["allowAnonymizedCollection"]
if "allowAnonymizedCollection" in verb_data.keys() else False,
)
for verb_object_data in verb_data["objects"]:
verb_object = VerbObject.objects.create(
verb=verb,
object_id=verb_object_data["id"],
label=verb_object_data["label"] if "label" in verb_object_data.keys() else "",
object_type=verb_object_data["objectType"] if "objectType" in verb_object_data.keys() else "Activity",
matching=verb_object_data["matching"] if "matching" in verb_object_data.keys() else "definitionType",
definition=verb_object_data["definition"]
)
group.verbs.add(verb)
if "objects" in verb_data.keys():
for verb_object_data in verb_data["objects"]:
VerbObject.objects.create(
verb=verb,
object_id=verb_object_data["id"],
label=verb_object_data["label"] if "label" in verb_object_data.keys() else "",
object_type=verb_object_data["objectType"] if "objectType" in verb_object_data.keys() else "Activity",
matching=verb_object_data["matching"] if "matching" in verb_object_data.keys() else "definitionType",
definition=verb_object_data["definition"]
)
if not group.verbs.filter(pk=verb.pk).exists():
group.verbs.add(verb)
for verb_data in essential_verbs:
try:
verb = Verb.objects.get(
......@@ -79,15 +81,16 @@ def migrate_schema_to_objects(apps, schema_editor):
allow_anonymized_collection=verb_data["allowAnonymizedCollection"]
if "allowAnonymizedCollection" in verb_data.keys() else False,
)
for verb_object_data in verb_data["objects"]:
verb_object = VerbObject.objects.create(
verb=verb,
object_id=verb_object_data["id"],
label=verb_object_data["label"] if "label" in verb_object_data.keys() else "",
object_type=verb_object_data["objectType"] if "objectType" in verb_object_data.keys() else "Activity",
matching=verb_object_data["matching"] if "matching" in verb_object_data.keys() else "definitionType",
definition=json.dumps(verb_object_data["definition"])
)
if "objects" in verb_data.keys():
for verb_object_data in verb_data["objects"]:
VerbObject.objects.create(
verb=verb,
object_id=verb_object_data["id"],
label=verb_object_data["label"] if "label" in verb_object_data.keys() else "",
object_type=verb_object_data["objectType"] if "objectType" in verb_object_data.keys() else "Activity",
matching=verb_object_data["matching"] if "matching" in verb_object_data.keys() else "definitionType",
definition=json.dumps(verb_object_data["definition"])
)
class Migration(migrations.Migration):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment