Add Edoniq testblock
WIP: Add sso code Update content name WIP: Add redirect endpoint mend Fix after rebase WIP: Update model WIP: Add extended time test url Update trufflehog config, use sso Update test
This commit is contained in:
parent
f7de5bae47
commit
c140f225ea
|
|
@ -106,6 +106,9 @@
|
||||||
"noDueDatesAvailable": "Keine Termine vorhanden",
|
"noDueDatesAvailable": "Keine Termine vorhanden",
|
||||||
"showAllDueDates": "Alle Termine anzeigen"
|
"showAllDueDates": "Alle Termine anzeigen"
|
||||||
},
|
},
|
||||||
|
"edoniqTest": {
|
||||||
|
"qualifiesForExtendedTime": "Ich habe Anrecht auf einen Nachteilsausgleich."
|
||||||
|
},
|
||||||
"feedback": {
|
"feedback": {
|
||||||
"answers": "Antworten",
|
"answers": "Antworten",
|
||||||
"areYouSatisfied": "Wie zufrieden bist du?",
|
"areYouSatisfied": "Wie zufrieden bist du?",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import LearningContentContainer from "@/pages/learningPath/learningContentPage/LearningContentContainer.vue";
|
import LearningContentContainer from "@/pages/learningPath/learningContentPage/LearningContentContainer.vue";
|
||||||
import DocumentListBlock from "@/pages/learningPath/learningContentPage/blocks/DocumentListBlock.vue";
|
import DocumentListBlock from "@/pages/learningPath/learningContentPage/blocks/DocumentListBlock.vue";
|
||||||
import TestBlock from "@/pages/learningPath/learningContentPage/blocks/TestBlock.vue";
|
import EdoniqTestBlock from "@/pages/learningPath/learningContentPage/blocks/EdoniqTestBlock.vue";
|
||||||
import { useCircleStore } from "@/stores/circle";
|
import { useCircleStore } from "@/stores/circle";
|
||||||
import type { LearningContent, LearningContentType } from "@/types";
|
import type { LearningContent, LearningContentType } from "@/types";
|
||||||
import eventBus from "@/utils/eventBus";
|
import eventBus from "@/utils/eventBus";
|
||||||
|
|
@ -35,7 +35,7 @@ const COMPONENTS: Record<LearningContentType, Component> = {
|
||||||
"learnpath.LearningContentMediaLibrary": MediaLibraryBlock,
|
"learnpath.LearningContentMediaLibrary": MediaLibraryBlock,
|
||||||
"learnpath.LearningContentPlaceholder": PlaceholderBlock,
|
"learnpath.LearningContentPlaceholder": PlaceholderBlock,
|
||||||
"learnpath.LearningContentRichText": RichTextBlock,
|
"learnpath.LearningContentRichText": RichTextBlock,
|
||||||
"learnpath.LearningContentTest": TestBlock,
|
"learnpath.LearningContentEdoniqTest": EdoniqTestBlock,
|
||||||
"learnpath.LearningContentVideo": VideoBlock,
|
"learnpath.LearningContentVideo": VideoBlock,
|
||||||
};
|
};
|
||||||
const DEFAULT_BLOCK = PlaceholderBlock;
|
const DEFAULT_BLOCK = PlaceholderBlock;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useTranslation } from "i18next-vue";
|
||||||
|
import ItCheckbox from "@/components/ui/ItCheckbox.vue";
|
||||||
|
import LearningContentSimpleLayout from "@/pages/learningPath/learningContentPage/layouts/LearningContentSimpleLayout.vue";
|
||||||
|
import type { LearningContentEdoniqTest } from "@/types";
|
||||||
|
import { ref } from "vue";
|
||||||
|
import * as log from "loglevel";
|
||||||
|
import { itPost } from "@/fetchHelpers";
|
||||||
|
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
content: LearningContentEdoniqTest;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const termsAccepted = ref(false);
|
||||||
|
const extendedTimeTest = ref(false);
|
||||||
|
|
||||||
|
async function startTest() {
|
||||||
|
log.info("start test", props.content);
|
||||||
|
const response = await itPost("/api/core/edoniq-test/redirect/", {
|
||||||
|
learning_content_id: props.content.id,
|
||||||
|
extended_time_test: extendedTimeTest.value,
|
||||||
|
});
|
||||||
|
log.info(response.redirect_url);
|
||||||
|
window.open(response.redirect_url, "_blank");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<LearningContentSimpleLayout
|
||||||
|
:title="props.content.title"
|
||||||
|
:learning-content="props.content"
|
||||||
|
>
|
||||||
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
|
<div class="container-medium">
|
||||||
|
<p
|
||||||
|
v-if="props.content.description"
|
||||||
|
class="default-wagtail-rich-text text-large my-4"
|
||||||
|
v-html="props.content.description"
|
||||||
|
></p>
|
||||||
|
|
||||||
|
<div class="my-8">
|
||||||
|
<ItCheckbox
|
||||||
|
v-if="props.content.checkbox_text"
|
||||||
|
:checkbox-item="{
|
||||||
|
label: props.content.checkbox_text,
|
||||||
|
value: termsAccepted,
|
||||||
|
checked: termsAccepted,
|
||||||
|
}"
|
||||||
|
@toggle="termsAccepted = !termsAccepted"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="my-8">
|
||||||
|
<ItCheckbox
|
||||||
|
v-if="props.content.has_extended_time_test"
|
||||||
|
:checkbox-item="{
|
||||||
|
label: t('edoniqTest.qualifiesForExtendedTime'),
|
||||||
|
value: extendedTimeTest,
|
||||||
|
checked: extendedTimeTest,
|
||||||
|
}"
|
||||||
|
@toggle="extendedTimeTest = !extendedTimeTest"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="my-8">
|
||||||
|
<button
|
||||||
|
:disabled="!termsAccepted"
|
||||||
|
class="btn-primary inline-flex items-center"
|
||||||
|
@click="startTest()"
|
||||||
|
>
|
||||||
|
Test starten
|
||||||
|
<it-icon-external-link class="it-icon ml-2 h-5 w-5"></it-icon-external-link>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</LearningContentSimpleLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!--<template>-->
|
||||||
|
|
||||||
|
<!-- <div class="container-medium">-->
|
||||||
|
|
||||||
|
<!-- <div class="lg:mt-8">-->
|
||||||
|
|
||||||
|
<!-- <h1>{{ content.title }}</h1>-->
|
||||||
|
|
||||||
|
<!-- <p class="text-large my-4 lg:my-8">{{ value.description }}</p>-->
|
||||||
|
|
||||||
|
<!-- <a :href="value.url" target="_blank" class="button btn-primary">Test starten</a>-->
|
||||||
|
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!--</template>-->
|
||||||
|
|
||||||
|
<!--<script setup lang="ts">-->
|
||||||
|
|
||||||
|
<!--import type { LearningContent } from "@/types";-->
|
||||||
|
|
||||||
|
<!--interface Value {-->
|
||||||
|
|
||||||
|
<!-- description: string;-->
|
||||||
|
|
||||||
|
<!-- url: string;-->
|
||||||
|
|
||||||
|
<!--}-->
|
||||||
|
|
||||||
|
<!--defineProps<{-->
|
||||||
|
|
||||||
|
<!-- value: Value;-->
|
||||||
|
|
||||||
|
<!-- content: LearningContent;-->
|
||||||
|
|
||||||
|
<!--}>();-->
|
||||||
|
|
||||||
|
<!--</script>-->
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import ItCheckbox from "@/components/ui/ItCheckbox.vue";
|
|
||||||
import LearningContentSimpleLayout from "@/pages/learningPath/learningContentPage/layouts/LearningContentSimpleLayout.vue";
|
|
||||||
import type { LearningContentTest } from "@/types";
|
|
||||||
import { ref } from "vue";
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
content: LearningContentTest;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const checked = ref(false);
|
|
||||||
|
|
||||||
function toggleChecked() {
|
|
||||||
checked.value = !checked.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function startTest() {
|
|
||||||
window.open(props.content.content_url, "_blank");
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<LearningContentSimpleLayout
|
|
||||||
:title="props.content.title"
|
|
||||||
:learning-content="props.content"
|
|
||||||
>
|
|
||||||
<!-- eslint-disable vue/no-v-html -->
|
|
||||||
<div class="container-medium">
|
|
||||||
<p
|
|
||||||
v-if="props.content.description"
|
|
||||||
class="default-wagtail-rich-text text-large my-4"
|
|
||||||
v-html="props.content.description"
|
|
||||||
></p>
|
|
||||||
|
|
||||||
<div class="my-8">
|
|
||||||
<ItCheckbox
|
|
||||||
v-if="props.content.checkbox_text"
|
|
||||||
:checkbox-item="{
|
|
||||||
label: props.content.checkbox_text,
|
|
||||||
value: checked,
|
|
||||||
checked: checked,
|
|
||||||
}"
|
|
||||||
@toggle="toggleChecked()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="my-8">
|
|
||||||
<button
|
|
||||||
:disabled="!checked"
|
|
||||||
class="btn-primary inline-flex items-center"
|
|
||||||
@click="startTest()"
|
|
||||||
>
|
|
||||||
Test starten
|
|
||||||
<it-icon-external-link class="it-icon ml-2 h-5 w-5"></it-icon-external-link>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</LearningContentSimpleLayout>
|
|
||||||
</template>
|
|
||||||
|
|
@ -26,7 +26,7 @@ function isLearningContentType(object: any): object is LearningContent {
|
||||||
object?.content_type === "learnpath.LearningContentMediaLibrary" ||
|
object?.content_type === "learnpath.LearningContentMediaLibrary" ||
|
||||||
object?.content_type === "learnpath.LearningContentPlaceholder" ||
|
object?.content_type === "learnpath.LearningContentPlaceholder" ||
|
||||||
object?.content_type === "learnpath.LearningContentRichText" ||
|
object?.content_type === "learnpath.LearningContentRichText" ||
|
||||||
object?.content_type === "learnpath.LearningContentTest" ||
|
object?.content_type === "learnpath.LearningContentEdoniqTest" ||
|
||||||
object?.content_type === "learnpath.LearningContentVideo"
|
object?.content_type === "learnpath.LearningContentVideo"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export type LearningContent =
|
||||||
| LearningContentMediaLibrary
|
| LearningContentMediaLibrary
|
||||||
| LearningContentPlaceholder
|
| LearningContentPlaceholder
|
||||||
| LearningContentRichText
|
| LearningContentRichText
|
||||||
| LearningContentTest
|
| LearningContentEdoniqTest
|
||||||
| LearningContentVideo;
|
| LearningContentVideo;
|
||||||
|
|
||||||
export type LearningContentType = LearningContent["content_type"];
|
export type LearningContentType = LearningContent["content_type"];
|
||||||
|
|
@ -93,9 +93,10 @@ export interface LearningContentRichText extends LearningContentInterface {
|
||||||
readonly text: string;
|
readonly text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LearningContentTest extends LearningContentInterface {
|
export interface LearningContentEdoniqTest extends LearningContentInterface {
|
||||||
readonly content_type: "learnpath.LearningContentTest";
|
readonly content_type: "learnpath.LearningContentEdoniqTest";
|
||||||
readonly checkbox_text: string;
|
readonly checkbox_text: string;
|
||||||
|
readonly has_extended_time_test: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LearningContentVideo extends LearningContentInterface {
|
export interface LearningContentVideo extends LearningContentInterface {
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ export function learningContentTypeData(
|
||||||
return { title: t("mediaLibrary.title"), icon: "it-icon-lc-media-library" };
|
return { title: t("mediaLibrary.title"), icon: "it-icon-lc-media-library" };
|
||||||
case "learnpath.LearningContentVideo":
|
case "learnpath.LearningContentVideo":
|
||||||
return { title: t("learningContentTypes.video"), icon: "it-icon-lc-video" };
|
return { title: t("learningContentTypes.video"), icon: "it-icon-lc-video" };
|
||||||
case "learnpath.LearningContentTest":
|
case "learnpath.LearningContentEdoniqTest":
|
||||||
return { title: t("learningContentTypes.test"), icon: "it-icon-lc-test" };
|
return { title: t("learningContentTypes.test"), icon: "it-icon-lc-test" };
|
||||||
case "learnpath.LearningContentRichText":
|
case "learnpath.LearningContentRichText":
|
||||||
return { title: t("learningContentTypes.text"), icon: "it-icon-lc-resource" };
|
return { title: t("learningContentTypes.text"), icon: "it-icon-lc-resource" };
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -640,6 +640,11 @@ GRAPHENE = {
|
||||||
# ],
|
# ],
|
||||||
# }
|
# }
|
||||||
|
|
||||||
|
# edoniq
|
||||||
|
|
||||||
|
EDONIQ_ENV = env("IT_EDONIQ_ENV", default="STEAGTEST")
|
||||||
|
EDONIQ_CERTIFICATE = env("IT_EDONIQ_CERTIFICATE", default="")
|
||||||
|
|
||||||
# Notifications
|
# Notifications
|
||||||
# django-notifications
|
# django-notifications
|
||||||
DJANGO_NOTIFICATIONS_CONFIG = {"SOFT_DELETE": True}
|
DJANGO_NOTIFICATIONS_CONFIG = {"SOFT_DELETE": True}
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ from django.urls import include, path, re_path, register_converter
|
||||||
from django.urls.converters import IntConverter
|
from django.urls.converters import IntConverter
|
||||||
from django.views import defaults as default_views
|
from django.views import defaults as default_views
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
from django_ratelimit.exceptions import Ratelimited
|
||||||
from graphene_django.views import GraphQLView
|
from graphene_django.views import GraphQLView
|
||||||
from ratelimit.exceptions import Ratelimited
|
|
||||||
|
|
||||||
from vbv_lernwelt.assignment.views import request_assignment_completion_status
|
from vbv_lernwelt.assignment.views import request_assignment_completion_status
|
||||||
from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt
|
from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt
|
||||||
|
|
@ -41,6 +41,7 @@ from vbv_lernwelt.edoniq_test.views import (
|
||||||
export_students,
|
export_students,
|
||||||
export_students_and_trainers,
|
export_students_and_trainers,
|
||||||
export_trainers,
|
export_trainers,
|
||||||
|
get_edoniq_token_redirect,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.feedback.views import (
|
from vbv_lernwelt.feedback.views import (
|
||||||
get_expert_feedbacks_for_course,
|
get_expert_feedbacks_for_course,
|
||||||
|
|
@ -146,10 +147,9 @@ urlpatterns = [
|
||||||
path(r'api/core/feedback/<str:course_session_id>/<str:circle_id>/', get_feedback_for_circle,
|
path(r'api/core/feedback/<str:course_session_id>/<str:circle_id>/', get_feedback_for_circle,
|
||||||
name='feedback_for_circle'),
|
name='feedback_for_circle'),
|
||||||
|
|
||||||
path("server/graphql/",
|
|
||||||
csrf_exempt(GraphQLView.as_view(graphiql=True, schema=schema))),
|
|
||||||
|
|
||||||
# edoniq test
|
# edoniq test
|
||||||
|
path(r'api/core/edoniq-test/redirect/', get_edoniq_token_redirect,
|
||||||
|
name='get_edoniq_token_redirect'),
|
||||||
path(r'api/core/edoniq-test/export-users/', export_students, name='edoniq_export_students'),
|
path(r'api/core/edoniq-test/export-users/', export_students, name='edoniq_export_students'),
|
||||||
path(r'api/core/edoniq-test/export-trainers/', export_trainers, name='edoniq_export_trainers'),
|
path(r'api/core/edoniq-test/export-trainers/', export_trainers, name='edoniq_export_trainers'),
|
||||||
path(r'api/core/edoniq-test/export-users-trainers/', export_students_and_trainers,
|
path(r'api/core/edoniq-test/export-users-trainers/', export_students_and_trainers,
|
||||||
|
|
@ -172,6 +172,8 @@ urlpatterns = [
|
||||||
name="t2l_sync",
|
name="t2l_sync",
|
||||||
),
|
),
|
||||||
|
|
||||||
|
path("server/graphql/",
|
||||||
|
csrf_exempt(GraphQLView.as_view(graphiql=True, schema=schema))),
|
||||||
# testing and debug
|
# testing and debug
|
||||||
path('server/raise_error/',
|
path('server/raise_error/',
|
||||||
user_passes_test(lambda u: u.is_superuser, login_url='/login/')(
|
user_passes_test(lambda u: u.is_superuser, login_url='/login/')(
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@
|
||||||
# This file is autogenerated by pip-compile with python 3.10
|
# This file is autogenerated by pip-compile with python 3.10
|
||||||
# To update, run:
|
# To update, run:
|
||||||
#
|
#
|
||||||
# pip-compile --output-file=requirements-dev.txt requirements-dev.in
|
# pip-compile requirements-dev.in
|
||||||
#
|
#
|
||||||
aniso8601==9.0.1
|
aniso8601==9.0.1
|
||||||
# via graphene
|
# via graphene
|
||||||
anyascii==0.3.1
|
anyascii==0.3.2
|
||||||
# via wagtail
|
# via wagtail
|
||||||
anyio==3.5.0
|
anyio==3.7.1
|
||||||
# via watchfiles
|
# via watchfiles
|
||||||
appnope==0.1.3
|
appnope==0.1.3
|
||||||
# via ipython
|
# via ipython
|
||||||
|
|
@ -16,64 +16,64 @@ argon2-cffi==21.3.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
argon2-cffi-bindings==21.2.0
|
argon2-cffi-bindings==21.2.0
|
||||||
# via argon2-cffi
|
# via argon2-cffi
|
||||||
asgiref==3.5.0
|
asgiref==3.7.2
|
||||||
# via django
|
# via django
|
||||||
astroid==2.11.2
|
astroid==2.15.6
|
||||||
# via pylint
|
# via pylint
|
||||||
asttokens==2.0.5
|
asttokens==2.2.1
|
||||||
# via stack-data
|
# via stack-data
|
||||||
async-timeout==4.0.2
|
async-timeout==4.0.2
|
||||||
# via redis
|
# via redis
|
||||||
attrs==21.4.0
|
attrs==23.1.0
|
||||||
# via
|
# via
|
||||||
# jsonschema
|
# jsonschema
|
||||||
# pytest
|
# referencing
|
||||||
# usort
|
# usort
|
||||||
authlib==1.0.0
|
authlib==1.2.1
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
azure-core==1.26.4
|
azure-core==1.29.1
|
||||||
# via
|
# via
|
||||||
# azure-identity
|
# azure-identity
|
||||||
# azure-storage-blob
|
# azure-storage-blob
|
||||||
azure-identity==1.13.0
|
azure-identity==1.14.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
azure-storage-blob==12.16.0
|
azure-storage-blob==12.17.0
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# django-storages
|
# django-storages
|
||||||
backcall==0.2.0
|
backcall==0.2.0
|
||||||
# via ipython
|
# via ipython
|
||||||
beautifulsoup4==4.9.3
|
beautifulsoup4==4.11.2
|
||||||
# via wagtail
|
# via wagtail
|
||||||
black==22.10.0
|
black==23.7.0
|
||||||
# via
|
# via
|
||||||
# -r requirements-dev.in
|
# -r requirements-dev.in
|
||||||
# ufmt
|
# ufmt
|
||||||
boto3==1.26.11
|
boto3==1.28.23
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
botocore==1.29.11
|
botocore==1.31.23
|
||||||
# via
|
# via
|
||||||
# boto3
|
# boto3
|
||||||
# s3transfer
|
# s3transfer
|
||||||
brotli==1.0.9
|
brotli==1.0.9
|
||||||
# via whitenoise
|
# via whitenoise
|
||||||
build==0.8.0
|
build==0.10.0
|
||||||
# via pip-tools
|
# via pip-tools
|
||||||
caprover-api @ git+https://github.com/iterativ/Caprover-API.git@5013f8fc929e8e3281b9d609e968a782e8e99530
|
caprover-api @ git+https://github.com/iterativ/Caprover-API.git@5013f8fc929e8e3281b9d609e968a782e8e99530
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
certifi==2021.10.8
|
certifi==2023.7.22
|
||||||
# via
|
# via
|
||||||
# requests
|
# requests
|
||||||
# sentry-sdk
|
# sentry-sdk
|
||||||
cffi==1.15.0
|
cffi==1.15.1
|
||||||
# via
|
# via
|
||||||
# argon2-cffi-bindings
|
# argon2-cffi-bindings
|
||||||
# cryptography
|
# cryptography
|
||||||
cfgv==3.3.1
|
cfgv==3.3.1
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
charset-normalizer==2.0.12
|
charset-normalizer==3.2.0
|
||||||
# via requests
|
# via requests
|
||||||
click==8.1.1
|
click==8.1.6
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# black
|
# black
|
||||||
|
|
@ -83,17 +83,13 @@ click==8.1.1
|
||||||
# ufmt
|
# ufmt
|
||||||
# usort
|
# usort
|
||||||
# uvicorn
|
# uvicorn
|
||||||
concurrent-log-handler==0.9.20
|
concurrent-log-handler==0.9.24
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
coreapi==2.3.3
|
coverage==7.2.7
|
||||||
# via djangorestframework-stubs
|
|
||||||
coreschema==0.0.4
|
|
||||||
# via coreapi
|
|
||||||
coverage==6.3.2
|
|
||||||
# via
|
# via
|
||||||
# -r requirements-dev.in
|
# -r requirements-dev.in
|
||||||
# django-coverage-plugin
|
# django-coverage-plugin
|
||||||
cryptography==36.0.2
|
cryptography==41.0.3
|
||||||
# via
|
# via
|
||||||
# authlib
|
# authlib
|
||||||
# azure-identity
|
# azure-identity
|
||||||
|
|
@ -104,15 +100,15 @@ decorator==5.1.1
|
||||||
# via
|
# via
|
||||||
# ipdb
|
# ipdb
|
||||||
# ipython
|
# ipython
|
||||||
deprecated==1.2.13
|
defusedxml==0.7.1
|
||||||
# via redis
|
# via willow
|
||||||
dill==0.3.4
|
dill==0.3.7
|
||||||
# via pylint
|
# via pylint
|
||||||
distlib==0.3.4
|
distlib==0.3.7
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
dj-database-url==1.0.0
|
dj-database-url==2.0.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django==3.2.13
|
django==3.2.20
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# dj-database-url
|
# dj-database-url
|
||||||
|
|
@ -138,27 +134,26 @@ django==3.2.13
|
||||||
# graphene-django
|
# graphene-django
|
||||||
# jsonfield
|
# jsonfield
|
||||||
# wagtail
|
# wagtail
|
||||||
# wagtail-grapple
|
|
||||||
# wagtail-localize
|
# wagtail-localize
|
||||||
django-click==2.3.0
|
django-click==2.3.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-cors-headers==3.11.0
|
django-cors-headers==4.2.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-coverage-plugin==2.0.2
|
django-coverage-plugin==3.1.0
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
django-csp==3.7
|
django-csp==3.7
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-debug-toolbar==3.2.4
|
django-debug-toolbar==4.1.0
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
django-extensions==3.2.0
|
django-extensions==3.2.3
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
django-filter==21.1
|
django-filter==23.2
|
||||||
# via wagtail
|
# via wagtail
|
||||||
django-ipware==4.0.2
|
django-ipware==5.0.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-jsonform==2.17.0
|
django-jsonform==2.18.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-model-utils==4.2.0
|
django-model-utils==4.3.1
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# django-notifications-hq
|
# django-notifications-hq
|
||||||
|
|
@ -168,64 +163,70 @@ django-notifications-hq==1.8.2
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-permissionedforms==0.1
|
django-permissionedforms==0.1
|
||||||
# via wagtail
|
# via wagtail
|
||||||
django-ratelimit==3.0.1
|
django-ratelimit==4.1.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-redis==5.2.0
|
django-redis==5.3.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-storages[azure]==1.13.1
|
django-storages[azure]==1.13.2
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-stubs==1.10.1
|
django-stubs==4.2.3
|
||||||
# via
|
# via
|
||||||
# -r requirements-dev.in
|
# -r requirements-dev.in
|
||||||
# djangorestframework-stubs
|
# djangorestframework-stubs
|
||||||
django-stubs-ext==0.4.0
|
django-stubs-ext==4.2.2
|
||||||
# via django-stubs
|
# via django-stubs
|
||||||
django-taggit==2.1.0
|
django-taggit==4.0.0
|
||||||
# via wagtail
|
# via wagtail
|
||||||
django-treebeard==4.5.1
|
django-treebeard==4.7
|
||||||
# via wagtail
|
# via wagtail
|
||||||
django-watchfiles @ https://github.com/q0w/django-watchfiles/archive/issue-1.zip
|
django-watchfiles @ https://github.com/q0w/django-watchfiles/archive/issue-1.zip
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
djangorestframework==3.13.1
|
djangorestframework==3.14.0
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# drf-spectacular
|
# drf-spectacular
|
||||||
# wagtail
|
# wagtail
|
||||||
djangorestframework-stubs==1.4.0
|
djangorestframework-stubs==3.14.2
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
draftjs-exporter==2.1.7
|
draftjs-exporter==2.1.7
|
||||||
# via wagtail
|
# via wagtail
|
||||||
drf-spectacular==0.22.0
|
drf-spectacular==0.26.4
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
environs==9.5.0
|
environs==9.5.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
et-xmlfile==1.1.0
|
et-xmlfile==1.1.0
|
||||||
# via openpyxl
|
# via openpyxl
|
||||||
executing==0.8.3
|
exceptiongroup==1.1.2
|
||||||
|
# via
|
||||||
|
# anyio
|
||||||
|
# pytest
|
||||||
|
executing==1.2.0
|
||||||
# via stack-data
|
# via stack-data
|
||||||
factory-boy==3.2.1
|
factory-boy==3.3.0
|
||||||
# via
|
# via
|
||||||
# -r requirements-dev.in
|
# -r requirements-dev.in
|
||||||
# wagtail-factories
|
# wagtail-factories
|
||||||
faker==13.3.4
|
faker==19.3.0
|
||||||
# via factory-boy
|
# via factory-boy
|
||||||
filelock==3.6.0
|
filelock==3.12.2
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
flake8==4.0.1
|
filetype==1.2.0
|
||||||
|
# via willow
|
||||||
|
flake8==6.1.0
|
||||||
# via
|
# via
|
||||||
# -r requirements-dev.in
|
# -r requirements-dev.in
|
||||||
# flake8-isort
|
# flake8-isort
|
||||||
flake8-isort==4.1.1
|
flake8-isort==6.0.0
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
gitdb==4.0.9
|
gitdb==4.0.10
|
||||||
# via gitdb2
|
# via gitdb2
|
||||||
gitdb2==4.0.2
|
gitdb2==4.0.2
|
||||||
# via gitpython
|
# via gitpython
|
||||||
gitpython==3.0.6
|
gitpython==3.0.6
|
||||||
# via trufflehog
|
# via trufflehog
|
||||||
graphene==3.2.2
|
graphene==3.3
|
||||||
# via graphene-django
|
# via graphene-django
|
||||||
graphene-django==3.0.0
|
graphene-django==3.1.5
|
||||||
# via wagtail-grapple
|
# via wagtail-grapple
|
||||||
graphql-core==3.2.3
|
graphql-core==3.2.3
|
||||||
# via
|
# via
|
||||||
|
|
@ -236,63 +237,59 @@ graphql-relay==3.2.0
|
||||||
# via
|
# via
|
||||||
# graphene
|
# graphene
|
||||||
# graphene-django
|
# graphene-django
|
||||||
gunicorn==20.1.0
|
gunicorn==21.2.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
h11==0.13.0
|
h11==0.14.0
|
||||||
# via uvicorn
|
# via uvicorn
|
||||||
html5lib==1.1
|
html5lib==1.1
|
||||||
# via wagtail
|
# via wagtail
|
||||||
httptools==0.4.0
|
httptools==0.6.0
|
||||||
# via uvicorn
|
# via uvicorn
|
||||||
identify==2.4.12
|
identify==2.5.26
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
idna==3.3
|
idna==3.4
|
||||||
# via
|
# via
|
||||||
# anyio
|
# anyio
|
||||||
# requests
|
# requests
|
||||||
inflection==0.5.1
|
inflection==0.5.1
|
||||||
# via drf-spectacular
|
# via drf-spectacular
|
||||||
iniconfig==1.1.1
|
iniconfig==2.0.0
|
||||||
# via pytest
|
# via pytest
|
||||||
ipdb==0.13.9
|
ipdb==0.13.13
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
ipython==8.2.0
|
ipython==8.14.0
|
||||||
# via ipdb
|
# via ipdb
|
||||||
isodate==0.6.1
|
isodate==0.6.1
|
||||||
# via azure-storage-blob
|
# via azure-storage-blob
|
||||||
isort==5.10.1
|
isort==5.12.0
|
||||||
# via
|
# via
|
||||||
# flake8-isort
|
# flake8-isort
|
||||||
# pylint
|
# pylint
|
||||||
itypes==1.2.0
|
jedi==0.19.0
|
||||||
# via coreapi
|
|
||||||
jedi==0.18.1
|
|
||||||
# via ipython
|
# via ipython
|
||||||
jinja2==3.1.1
|
|
||||||
# via coreschema
|
|
||||||
jmespath==1.0.1
|
jmespath==1.0.1
|
||||||
# via
|
# via
|
||||||
# boto3
|
# boto3
|
||||||
# botocore
|
# botocore
|
||||||
jsonfield==3.1.0
|
jsonfield==3.1.0
|
||||||
# via django-notifications-hq
|
# via django-notifications-hq
|
||||||
jsonschema==4.4.0
|
jsonschema==4.19.0
|
||||||
# via drf-spectacular
|
# via drf-spectacular
|
||||||
|
jsonschema-specifications==2023.7.1
|
||||||
|
# via jsonschema
|
||||||
l18n==2021.3
|
l18n==2021.3
|
||||||
# via wagtail
|
# via wagtail
|
||||||
lazy-object-proxy==1.7.1
|
lazy-object-proxy==1.9.0
|
||||||
# via astroid
|
# via astroid
|
||||||
libcst==0.4.7
|
libcst==1.0.1
|
||||||
# via
|
# via
|
||||||
# ufmt
|
# ufmt
|
||||||
# usort
|
# usort
|
||||||
markupsafe==2.1.1
|
marshmallow==3.20.1
|
||||||
# via jinja2
|
|
||||||
marshmallow==3.15.0
|
|
||||||
# via environs
|
# via environs
|
||||||
matplotlib-inline==0.1.3
|
matplotlib-inline==0.1.6
|
||||||
# via ipython
|
# via ipython
|
||||||
mccabe==0.6.1
|
mccabe==0.7.0
|
||||||
# via
|
# via
|
||||||
# flake8
|
# flake8
|
||||||
# pylint
|
# pylint
|
||||||
|
|
@ -300,127 +297,127 @@ moreorless==0.4.0
|
||||||
# via
|
# via
|
||||||
# ufmt
|
# ufmt
|
||||||
# usort
|
# usort
|
||||||
msal==1.22.0
|
msal==1.23.0
|
||||||
# via
|
# via
|
||||||
# azure-identity
|
# azure-identity
|
||||||
# msal-extensions
|
# msal-extensions
|
||||||
msal-extensions==1.0.0
|
msal-extensions==1.0.0
|
||||||
# via azure-identity
|
# via azure-identity
|
||||||
mypy==0.942
|
mypy==1.4.1
|
||||||
# via
|
# via
|
||||||
# -r requirements-dev.in
|
# -r requirements-dev.in
|
||||||
# django-stubs
|
# django-stubs
|
||||||
# djangorestframework-stubs
|
# djangorestframework-stubs
|
||||||
mypy-extensions==0.4.3
|
mypy-extensions==1.0.0
|
||||||
# via
|
# via
|
||||||
# black
|
# black
|
||||||
# mypy
|
# mypy
|
||||||
# typing-inspect
|
# typing-inspect
|
||||||
nodeenv==1.6.0
|
nodeenv==1.8.0
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
openpyxl==3.1.2
|
openpyxl==3.1.2
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# wagtail
|
# wagtail
|
||||||
packaging==21.3
|
packaging==23.1
|
||||||
# via
|
# via
|
||||||
|
# black
|
||||||
# build
|
# build
|
||||||
|
# gunicorn
|
||||||
# marshmallow
|
# marshmallow
|
||||||
# pytest
|
# pytest
|
||||||
# pytest-sugar
|
# pytest-sugar
|
||||||
# redis
|
|
||||||
parso==0.8.3
|
parso==0.8.3
|
||||||
# via jedi
|
# via jedi
|
||||||
pathspec==0.9.0
|
pathspec==0.11.2
|
||||||
# via
|
# via
|
||||||
# black
|
# black
|
||||||
# trailrunner
|
# trailrunner
|
||||||
pep517==0.12.0
|
|
||||||
# via build
|
|
||||||
pexpect==4.8.0
|
pexpect==4.8.0
|
||||||
# via ipython
|
# via ipython
|
||||||
pickleshare==0.7.5
|
pickleshare==0.7.5
|
||||||
# via ipython
|
# via ipython
|
||||||
pillow==9.0.1
|
pillow==10.0.0
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
|
# pillow-heif
|
||||||
# wagtail
|
# wagtail
|
||||||
pip-tools==6.9.0
|
pillow-heif==0.13.0
|
||||||
|
# via willow
|
||||||
|
pip-tools==7.3.0
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
platformdirs==2.5.1
|
platformdirs==3.10.0
|
||||||
# via
|
# via
|
||||||
# black
|
# black
|
||||||
# pylint
|
# pylint
|
||||||
# virtualenv
|
# virtualenv
|
||||||
pluggy==1.0.0
|
pluggy==1.2.0
|
||||||
# via pytest
|
# via pytest
|
||||||
polib==1.1.1
|
polib==1.2.0
|
||||||
# via wagtail-localize
|
# via wagtail-localize
|
||||||
portalocker==2.4.0
|
portalocker==2.7.0
|
||||||
# via
|
# via
|
||||||
# concurrent-log-handler
|
# concurrent-log-handler
|
||||||
# msal-extensions
|
# msal-extensions
|
||||||
pre-commit==2.17.0
|
pre-commit==3.3.3
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
promise==2.3
|
promise==2.3
|
||||||
# via graphene-django
|
# via graphene-django
|
||||||
prompt-toolkit==3.0.28
|
prompt-toolkit==3.0.39
|
||||||
# via ipython
|
# via ipython
|
||||||
psycopg2-binary==2.9.3
|
psycopg2-binary==2.9.7
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
ptyprocess==0.7.0
|
ptyprocess==0.7.0
|
||||||
# via pexpect
|
# via pexpect
|
||||||
pure-eval==0.2.2
|
pure-eval==0.2.2
|
||||||
# via stack-data
|
# via stack-data
|
||||||
py==1.11.0
|
pycodestyle==2.11.0
|
||||||
# via pytest
|
|
||||||
pycodestyle==2.8.0
|
|
||||||
# via flake8
|
# via flake8
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
pyflakes==2.4.0
|
pycryptodome==3.18.0
|
||||||
|
# via -r requirements.in
|
||||||
|
pyflakes==3.1.0
|
||||||
# via flake8
|
# via flake8
|
||||||
pygments==2.11.2
|
pygments==2.16.1
|
||||||
# via ipython
|
# via ipython
|
||||||
pyjwt[crypto]==2.7.0
|
pyjwt[crypto]==2.8.0
|
||||||
# via msal
|
# via msal
|
||||||
pylint==2.13.4
|
pylint==2.17.5
|
||||||
# via
|
# via
|
||||||
# pylint-django
|
# pylint-django
|
||||||
# pylint-plugin-utils
|
# pylint-plugin-utils
|
||||||
pylint-django==2.5.3
|
pylint-django==2.5.3
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
pylint-plugin-utils==0.7
|
pylint-plugin-utils==0.8.2
|
||||||
# via pylint-django
|
# via pylint-django
|
||||||
pyparsing==3.0.7
|
pyproject-hooks==1.0.0
|
||||||
# via packaging
|
# via build
|
||||||
pyrsistent==0.18.1
|
pytest==7.4.0
|
||||||
# via jsonschema
|
|
||||||
pytest==7.1.3
|
|
||||||
# via
|
# via
|
||||||
# -r requirements-dev.in
|
# -r requirements-dev.in
|
||||||
# pytest-django
|
# pytest-django
|
||||||
# pytest-sugar
|
# pytest-sugar
|
||||||
pytest-django==4.5.2
|
pytest-django==4.5.2
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
pytest-sugar==0.9.4
|
pytest-sugar==0.9.7
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
python-dateutil==2.8.2
|
python-dateutil==2.8.2
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# botocore
|
# botocore
|
||||||
# faker
|
# faker
|
||||||
python-dotenv==0.20.0
|
python-dotenv==1.0.0
|
||||||
# via
|
# via
|
||||||
# environs
|
# environs
|
||||||
# uvicorn
|
# uvicorn
|
||||||
python-http-client==3.3.7
|
python-http-client==3.3.7
|
||||||
# via sendgrid
|
# via sendgrid
|
||||||
python-json-logger==2.0.2
|
python-json-logger==2.0.7
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
python-slugify==6.1.1
|
python-slugify==8.0.1
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
pytz==2022.1
|
pytz==2023.3
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# django
|
# django
|
||||||
|
|
@ -428,94 +425,97 @@ pytz==2022.1
|
||||||
# django-notifications-hq
|
# django-notifications-hq
|
||||||
# djangorestframework
|
# djangorestframework
|
||||||
# l18n
|
# l18n
|
||||||
pyyaml==6.0
|
pyyaml==6.0.1
|
||||||
# via
|
# via
|
||||||
# caprover-api
|
# caprover-api
|
||||||
# drf-spectacular
|
# drf-spectacular
|
||||||
# libcst
|
# libcst
|
||||||
# pre-commit
|
# pre-commit
|
||||||
# uvicorn
|
# uvicorn
|
||||||
redis==4.2.1
|
redis==4.6.0
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# django-redis
|
# django-redis
|
||||||
requests==2.27.1
|
referencing==0.30.2
|
||||||
|
# via
|
||||||
|
# jsonschema
|
||||||
|
# jsonschema-specifications
|
||||||
|
requests==2.31.0
|
||||||
# via
|
# via
|
||||||
# azure-core
|
# azure-core
|
||||||
# caprover-api
|
# caprover-api
|
||||||
# coreapi
|
|
||||||
# djangorestframework-stubs
|
# djangorestframework-stubs
|
||||||
# msal
|
# msal
|
||||||
# wagtail
|
# wagtail
|
||||||
s3transfer==0.6.0
|
rpds-py==0.9.2
|
||||||
|
# via
|
||||||
|
# jsonschema
|
||||||
|
# referencing
|
||||||
|
s3transfer==0.6.1
|
||||||
# via boto3
|
# via boto3
|
||||||
sendgrid==6.9.7
|
sendgrid==6.10.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
sentry-sdk==1.5.8
|
sentry-sdk==1.29.2
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
six==1.16.0
|
six==1.16.0
|
||||||
# via
|
# via
|
||||||
# asttokens
|
# asttokens
|
||||||
# azure-core
|
# azure-core
|
||||||
# azure-identity
|
|
||||||
# django-coverage-plugin
|
|
||||||
# html5lib
|
# html5lib
|
||||||
# isodate
|
# isodate
|
||||||
# l18n
|
# l18n
|
||||||
# promise
|
# promise
|
||||||
# python-dateutil
|
# python-dateutil
|
||||||
# virtualenv
|
|
||||||
smmap==5.0.0
|
smmap==5.0.0
|
||||||
# via gitdb
|
# via gitdb
|
||||||
sniffio==1.2.0
|
sniffio==1.3.0
|
||||||
# via anyio
|
# via anyio
|
||||||
soupsieve==2.3.2.post1
|
soupsieve==2.4.1
|
||||||
# via beautifulsoup4
|
# via beautifulsoup4
|
||||||
sqlparse==0.4.2
|
sqlparse==0.4.4
|
||||||
# via
|
# via
|
||||||
# django
|
# django
|
||||||
# django-debug-toolbar
|
# django-debug-toolbar
|
||||||
stack-data==0.2.0
|
stack-data==0.6.2
|
||||||
# via ipython
|
# via ipython
|
||||||
starkbank-ecdsa==2.2.0
|
starkbank-ecdsa==2.2.0
|
||||||
# via sendgrid
|
# via sendgrid
|
||||||
stdlibs==2022.6.8
|
stdlibs==2022.10.9
|
||||||
# via usort
|
# via usort
|
||||||
structlog==21.5.0
|
structlog==23.1.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
swapper==1.3.0
|
swapper==1.3.0
|
||||||
# via django-notifications-hq
|
# via django-notifications-hq
|
||||||
telepath==0.2
|
telepath==0.3.1
|
||||||
# via wagtail
|
# via wagtail
|
||||||
termcolor==1.1.0
|
termcolor==2.3.0
|
||||||
# via pytest-sugar
|
# via pytest-sugar
|
||||||
testfixtures==6.18.5
|
|
||||||
# via flake8-isort
|
|
||||||
text-unidecode==1.3
|
text-unidecode==1.3
|
||||||
# via
|
# via
|
||||||
# graphene-django
|
# graphene-django
|
||||||
# python-slugify
|
# python-slugify
|
||||||
toml==0.10.2
|
toml==0.10.2
|
||||||
# via
|
# via usort
|
||||||
# ipdb
|
|
||||||
# pre-commit
|
|
||||||
# usort
|
|
||||||
tomli==2.0.1
|
tomli==2.0.1
|
||||||
# via
|
# via
|
||||||
# black
|
# black
|
||||||
# build
|
# build
|
||||||
# django-stubs
|
# django-stubs
|
||||||
|
# ipdb
|
||||||
# mypy
|
# mypy
|
||||||
# pep517
|
# pip-tools
|
||||||
# pylint
|
# pylint
|
||||||
|
# pyproject-hooks
|
||||||
# pytest
|
# pytest
|
||||||
tomlkit==0.11.5
|
tomlkit==0.12.1
|
||||||
# via ufmt
|
# via
|
||||||
trailrunner==1.2.1
|
# pylint
|
||||||
|
# ufmt
|
||||||
|
trailrunner==1.4.0
|
||||||
# via
|
# via
|
||||||
# ufmt
|
# ufmt
|
||||||
# usort
|
# usort
|
||||||
traitlets==5.1.1
|
traitlets==5.9.0
|
||||||
# via
|
# via
|
||||||
# ipython
|
# ipython
|
||||||
# matplotlib-inline
|
# matplotlib-inline
|
||||||
|
|
@ -523,14 +523,23 @@ trufflehog==2.2.1
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
trufflehogregexes==0.0.7
|
trufflehogregexes==0.0.7
|
||||||
# via trufflehog
|
# via trufflehog
|
||||||
types-pytz==2021.3.6
|
types-pytz==2023.3.0.0
|
||||||
# via django-stubs
|
# via django-stubs
|
||||||
types-pyyaml==6.0.5
|
types-pyyaml==6.0.12.11
|
||||||
# via django-stubs
|
|
||||||
typing-extensions==4.5.0
|
|
||||||
# via
|
# via
|
||||||
|
# django-stubs
|
||||||
|
# djangorestframework-stubs
|
||||||
|
types-requests==2.31.0.2
|
||||||
|
# via djangorestframework-stubs
|
||||||
|
types-urllib3==1.26.25.14
|
||||||
|
# via types-requests
|
||||||
|
typing-extensions==4.7.1
|
||||||
|
# via
|
||||||
|
# asgiref
|
||||||
|
# astroid
|
||||||
# azure-core
|
# azure-core
|
||||||
# azure-storage-blob
|
# azure-storage-blob
|
||||||
|
# dj-database-url
|
||||||
# django-stubs
|
# django-stubs
|
||||||
# django-stubs-ext
|
# django-stubs-ext
|
||||||
# djangorestframework-stubs
|
# djangorestframework-stubs
|
||||||
|
|
@ -538,63 +547,60 @@ typing-extensions==4.5.0
|
||||||
# mypy
|
# mypy
|
||||||
# typing-inspect
|
# typing-inspect
|
||||||
# ufmt
|
# ufmt
|
||||||
|
# uvicorn
|
||||||
# wagtail-localize
|
# wagtail-localize
|
||||||
typing-inspect==0.8.0
|
typing-inspect==0.9.0
|
||||||
# via libcst
|
# via libcst
|
||||||
ufmt==2.0.1
|
ufmt==2.2.0
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
uritemplate==4.1.1
|
uritemplate==4.1.1
|
||||||
# via
|
# via drf-spectacular
|
||||||
# coreapi
|
urllib3==1.26.16
|
||||||
# drf-spectacular
|
|
||||||
urllib3==1.26.9
|
|
||||||
# via
|
# via
|
||||||
# botocore
|
# botocore
|
||||||
# requests
|
# requests
|
||||||
# sentry-sdk
|
# sentry-sdk
|
||||||
usort==1.0.5
|
usort==1.0.7
|
||||||
# via ufmt
|
# via ufmt
|
||||||
uvicorn[standard]==0.18.3
|
uvicorn[standard]==0.23.2
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
uvloop==0.16.0
|
uvloop==0.17.0
|
||||||
# via uvicorn
|
# via uvicorn
|
||||||
virtualenv==20.14.0
|
virtualenv==20.24.2
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
wagtail==4.2.2
|
wagtail==5.1
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# wagtail-factories
|
# wagtail-factories
|
||||||
# wagtail-grapple
|
# wagtail-grapple
|
||||||
# wagtail-headless-preview
|
# wagtail-headless-preview
|
||||||
# wagtail-localize
|
# wagtail-localize
|
||||||
wagtail-factories==4.0.0
|
wagtail-factories==4.1.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
wagtail-grapple==0.19.2
|
wagtail-grapple==0.20.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
wagtail-headless-preview==0.4.0
|
wagtail-headless-preview==0.6.0
|
||||||
# via wagtail-grapple
|
# via wagtail-grapple
|
||||||
wagtail-localize==1.5
|
wagtail-localize==1.5.1
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
watchfiles==0.17.0
|
watchfiles==0.19.0
|
||||||
# via
|
# via
|
||||||
# django-watchfiles
|
# django-watchfiles
|
||||||
# uvicorn
|
# uvicorn
|
||||||
wcwidth==0.2.5
|
wcwidth==0.2.6
|
||||||
# via prompt-toolkit
|
# via prompt-toolkit
|
||||||
webencodings==0.5.1
|
webencodings==0.5.1
|
||||||
# via html5lib
|
# via html5lib
|
||||||
websockets==10.2
|
websockets==11.0.3
|
||||||
# via uvicorn
|
# via uvicorn
|
||||||
wheel==0.37.1
|
wheel==0.41.1
|
||||||
# via pip-tools
|
# via pip-tools
|
||||||
whitenoise[brotli]==6.0.0
|
whitenoise[brotli]==6.5.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
willow==1.4.1
|
willow[heif]==1.6.1
|
||||||
# via wagtail
|
# via wagtail
|
||||||
wrapt==1.14.0
|
wrapt==1.15.0
|
||||||
# via
|
# via astroid
|
||||||
# astroid
|
|
||||||
# deprecated
|
|
||||||
|
|
||||||
# The following packages are considered to be unsafe in a requirements file:
|
# The following packages are considered to be unsafe in a requirements file:
|
||||||
# pip
|
# pip
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ structlog
|
||||||
python-json-logger
|
python-json-logger
|
||||||
concurrent-log-handler
|
concurrent-log-handler
|
||||||
python-dateutil
|
python-dateutil
|
||||||
|
pycryptodome
|
||||||
|
|
||||||
wagtail>=4
|
wagtail>=4
|
||||||
wagtail-factories>=4
|
wagtail-factories>=4
|
||||||
|
|
|
||||||
|
|
@ -2,75 +2,77 @@
|
||||||
# This file is autogenerated by pip-compile with python 3.10
|
# This file is autogenerated by pip-compile with python 3.10
|
||||||
# To update, run:
|
# To update, run:
|
||||||
#
|
#
|
||||||
# pip-compile --output-file=requirements.txt requirements.in
|
# pip-compile requirements.in
|
||||||
#
|
#
|
||||||
aniso8601==9.0.1
|
aniso8601==9.0.1
|
||||||
# via graphene
|
# via graphene
|
||||||
anyascii==0.3.1
|
anyascii==0.3.2
|
||||||
# via wagtail
|
# via wagtail
|
||||||
anyio==3.5.0
|
anyio==3.7.1
|
||||||
# via watchfiles
|
# via watchfiles
|
||||||
argon2-cffi==21.3.0
|
argon2-cffi==21.3.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
argon2-cffi-bindings==21.2.0
|
argon2-cffi-bindings==21.2.0
|
||||||
# via argon2-cffi
|
# via argon2-cffi
|
||||||
asgiref==3.5.0
|
asgiref==3.7.2
|
||||||
# via django
|
# via django
|
||||||
async-timeout==4.0.2
|
async-timeout==4.0.2
|
||||||
# via redis
|
# via redis
|
||||||
attrs==21.4.0
|
attrs==23.1.0
|
||||||
# via jsonschema
|
# via
|
||||||
authlib==1.0.0
|
# jsonschema
|
||||||
|
# referencing
|
||||||
|
authlib==1.2.1
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
azure-core==1.26.4
|
azure-core==1.29.1
|
||||||
# via
|
# via
|
||||||
# azure-identity
|
# azure-identity
|
||||||
# azure-storage-blob
|
# azure-storage-blob
|
||||||
azure-identity==1.13.0
|
azure-identity==1.14.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
azure-storage-blob==12.16.0
|
azure-storage-blob==12.17.0
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# django-storages
|
# django-storages
|
||||||
beautifulsoup4==4.9.3
|
beautifulsoup4==4.11.2
|
||||||
# via wagtail
|
# via wagtail
|
||||||
boto3==1.26.11
|
boto3==1.28.23
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
botocore==1.29.11
|
botocore==1.31.23
|
||||||
# via
|
# via
|
||||||
# boto3
|
# boto3
|
||||||
# s3transfer
|
# s3transfer
|
||||||
brotli==1.0.9
|
brotli==1.0.9
|
||||||
# via whitenoise
|
# via whitenoise
|
||||||
certifi==2021.10.8
|
certifi==2023.7.22
|
||||||
# via
|
# via
|
||||||
# requests
|
# requests
|
||||||
# sentry-sdk
|
# sentry-sdk
|
||||||
cffi==1.15.0
|
cffi==1.15.1
|
||||||
# via
|
# via
|
||||||
# argon2-cffi-bindings
|
# argon2-cffi-bindings
|
||||||
# cryptography
|
# cryptography
|
||||||
charset-normalizer==2.0.12
|
charset-normalizer==3.2.0
|
||||||
# via requests
|
# via requests
|
||||||
click==8.1.1
|
click==8.1.6
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# django-click
|
# django-click
|
||||||
# uvicorn
|
# uvicorn
|
||||||
concurrent-log-handler==0.9.20
|
concurrent-log-handler==0.9.24
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
cryptography==36.0.2
|
cryptography==41.0.3
|
||||||
# via
|
# via
|
||||||
# authlib
|
# authlib
|
||||||
# azure-identity
|
# azure-identity
|
||||||
# azure-storage-blob
|
# azure-storage-blob
|
||||||
# msal
|
# msal
|
||||||
# pyjwt
|
# pyjwt
|
||||||
deprecated==1.2.13
|
defusedxml==0.7.1
|
||||||
# via redis
|
# via willow
|
||||||
dj-database-url==1.0.0
|
dj-database-url==2.0.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django==3.2.13
|
django==3.2.20
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# dj-database-url
|
# dj-database-url
|
||||||
|
|
@ -91,21 +93,20 @@ django==3.2.13
|
||||||
# graphene-django
|
# graphene-django
|
||||||
# jsonfield
|
# jsonfield
|
||||||
# wagtail
|
# wagtail
|
||||||
# wagtail-grapple
|
|
||||||
# wagtail-localize
|
# wagtail-localize
|
||||||
django-click==2.3.0
|
django-click==2.3.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-cors-headers==3.11.0
|
django-cors-headers==4.2.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-csp==3.7
|
django-csp==3.7
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-filter==21.1
|
django-filter==23.2
|
||||||
# via wagtail
|
# via wagtail
|
||||||
django-ipware==4.0.2
|
django-ipware==5.0.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-jsonform==2.17.0
|
django-jsonform==2.18.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-model-utils==4.2.0
|
django-model-utils==4.3.1
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# django-notifications-hq
|
# django-notifications-hq
|
||||||
|
|
@ -115,36 +116,40 @@ django-notifications-hq==1.8.2
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-permissionedforms==0.1
|
django-permissionedforms==0.1
|
||||||
# via wagtail
|
# via wagtail
|
||||||
django-ratelimit==3.0.1
|
django-ratelimit==4.1.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-redis==5.2.0
|
django-redis==5.3.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-storages[azure]==1.13.1
|
django-storages[azure]==1.13.2
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-taggit==2.1.0
|
django-taggit==4.0.0
|
||||||
# via wagtail
|
# via wagtail
|
||||||
django-treebeard==4.5.1
|
django-treebeard==4.7
|
||||||
# via wagtail
|
# via wagtail
|
||||||
djangorestframework==3.13.1
|
djangorestframework==3.14.0
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# drf-spectacular
|
# drf-spectacular
|
||||||
# wagtail
|
# wagtail
|
||||||
draftjs-exporter==2.1.7
|
draftjs-exporter==2.1.7
|
||||||
# via wagtail
|
# via wagtail
|
||||||
drf-spectacular==0.22.0
|
drf-spectacular==0.26.4
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
environs==9.5.0
|
environs==9.5.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
et-xmlfile==1.1.0
|
et-xmlfile==1.1.0
|
||||||
# via openpyxl
|
# via openpyxl
|
||||||
factory-boy==3.2.1
|
exceptiongroup==1.1.2
|
||||||
|
# via anyio
|
||||||
|
factory-boy==3.3.0
|
||||||
# via wagtail-factories
|
# via wagtail-factories
|
||||||
faker==13.11.1
|
faker==19.3.0
|
||||||
# via factory-boy
|
# via factory-boy
|
||||||
graphene==3.2.2
|
filetype==1.2.0
|
||||||
|
# via willow
|
||||||
|
graphene==3.3
|
||||||
# via graphene-django
|
# via graphene-django
|
||||||
graphene-django==3.0.0
|
graphene-django==3.1.5
|
||||||
# via wagtail-grapple
|
# via wagtail-grapple
|
||||||
graphql-core==3.2.3
|
graphql-core==3.2.3
|
||||||
# via
|
# via
|
||||||
|
|
@ -155,15 +160,15 @@ graphql-relay==3.2.0
|
||||||
# via
|
# via
|
||||||
# graphene
|
# graphene
|
||||||
# graphene-django
|
# graphene-django
|
||||||
gunicorn==20.1.0
|
gunicorn==21.2.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
h11==0.13.0
|
h11==0.14.0
|
||||||
# via uvicorn
|
# via uvicorn
|
||||||
html5lib==1.1
|
html5lib==1.1
|
||||||
# via wagtail
|
# via wagtail
|
||||||
httptools==0.4.0
|
httptools==0.6.0
|
||||||
# via uvicorn
|
# via uvicorn
|
||||||
idna==3.3
|
idna==3.4
|
||||||
# via
|
# via
|
||||||
# anyio
|
# anyio
|
||||||
# requests
|
# requests
|
||||||
|
|
@ -177,13 +182,15 @@ jmespath==1.0.1
|
||||||
# botocore
|
# botocore
|
||||||
jsonfield==3.1.0
|
jsonfield==3.1.0
|
||||||
# via django-notifications-hq
|
# via django-notifications-hq
|
||||||
jsonschema==4.4.0
|
jsonschema==4.19.0
|
||||||
# via drf-spectacular
|
# via drf-spectacular
|
||||||
|
jsonschema-specifications==2023.7.1
|
||||||
|
# via jsonschema
|
||||||
l18n==2021.3
|
l18n==2021.3
|
||||||
# via wagtail
|
# via wagtail
|
||||||
marshmallow==3.15.0
|
marshmallow==3.20.1
|
||||||
# via environs
|
# via environs
|
||||||
msal==1.22.0
|
msal==1.23.0
|
||||||
# via
|
# via
|
||||||
# azure-identity
|
# azure-identity
|
||||||
# msal-extensions
|
# msal-extensions
|
||||||
|
|
@ -193,48 +200,49 @@ openpyxl==3.1.2
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# wagtail
|
# wagtail
|
||||||
packaging==21.3
|
packaging==23.1
|
||||||
# via
|
# via
|
||||||
|
# gunicorn
|
||||||
# marshmallow
|
# marshmallow
|
||||||
# redis
|
pillow==10.0.0
|
||||||
pillow==9.0.1
|
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
|
# pillow-heif
|
||||||
# wagtail
|
# wagtail
|
||||||
polib==1.1.1
|
pillow-heif==0.13.0
|
||||||
|
# via willow
|
||||||
|
polib==1.2.0
|
||||||
# via wagtail-localize
|
# via wagtail-localize
|
||||||
portalocker==2.4.0
|
portalocker==2.7.0
|
||||||
# via
|
# via
|
||||||
# concurrent-log-handler
|
# concurrent-log-handler
|
||||||
# msal-extensions
|
# msal-extensions
|
||||||
promise==2.3
|
promise==2.3
|
||||||
# via graphene-django
|
# via graphene-django
|
||||||
psycopg2-binary==2.9.3
|
psycopg2-binary==2.9.7
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
pyjwt[crypto]==2.7.0
|
pycryptodome==3.18.0
|
||||||
|
# via -r requirements.in
|
||||||
|
pyjwt[crypto]==2.8.0
|
||||||
# via msal
|
# via msal
|
||||||
pyparsing==3.0.7
|
|
||||||
# via packaging
|
|
||||||
pyrsistent==0.18.1
|
|
||||||
# via jsonschema
|
|
||||||
python-dateutil==2.8.2
|
python-dateutil==2.8.2
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# botocore
|
# botocore
|
||||||
# faker
|
# faker
|
||||||
python-dotenv==0.20.0
|
python-dotenv==1.0.0
|
||||||
# via
|
# via
|
||||||
# environs
|
# environs
|
||||||
# uvicorn
|
# uvicorn
|
||||||
python-http-client==3.3.7
|
python-http-client==3.3.7
|
||||||
# via sendgrid
|
# via sendgrid
|
||||||
python-json-logger==2.0.2
|
python-json-logger==2.0.7
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
python-slugify==6.1.1
|
python-slugify==8.0.1
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
pytz==2022.1
|
pytz==2023.3
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# django
|
# django
|
||||||
|
|
@ -242,95 +250,100 @@ pytz==2022.1
|
||||||
# django-notifications-hq
|
# django-notifications-hq
|
||||||
# djangorestframework
|
# djangorestframework
|
||||||
# l18n
|
# l18n
|
||||||
pyyaml==6.0
|
pyyaml==6.0.1
|
||||||
# via
|
# via
|
||||||
# drf-spectacular
|
# drf-spectacular
|
||||||
# uvicorn
|
# uvicorn
|
||||||
redis==4.2.1
|
redis==4.6.0
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# django-redis
|
# django-redis
|
||||||
requests==2.27.1
|
referencing==0.30.2
|
||||||
|
# via
|
||||||
|
# jsonschema
|
||||||
|
# jsonschema-specifications
|
||||||
|
requests==2.31.0
|
||||||
# via
|
# via
|
||||||
# azure-core
|
# azure-core
|
||||||
# msal
|
# msal
|
||||||
# wagtail
|
# wagtail
|
||||||
s3transfer==0.6.0
|
rpds-py==0.9.2
|
||||||
|
# via
|
||||||
|
# jsonschema
|
||||||
|
# referencing
|
||||||
|
s3transfer==0.6.1
|
||||||
# via boto3
|
# via boto3
|
||||||
sendgrid==6.9.7
|
sendgrid==6.10.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
sentry-sdk==1.5.8
|
sentry-sdk==1.29.2
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
six==1.16.0
|
six==1.16.0
|
||||||
# via
|
# via
|
||||||
# azure-core
|
# azure-core
|
||||||
# azure-identity
|
|
||||||
# html5lib
|
# html5lib
|
||||||
# isodate
|
# isodate
|
||||||
# l18n
|
# l18n
|
||||||
# promise
|
# promise
|
||||||
# python-dateutil
|
# python-dateutil
|
||||||
sniffio==1.2.0
|
sniffio==1.3.0
|
||||||
# via anyio
|
# via anyio
|
||||||
soupsieve==2.3.2.post1
|
soupsieve==2.4.1
|
||||||
# via beautifulsoup4
|
# via beautifulsoup4
|
||||||
sqlparse==0.4.2
|
sqlparse==0.4.4
|
||||||
# via django
|
# via django
|
||||||
starkbank-ecdsa==2.2.0
|
starkbank-ecdsa==2.2.0
|
||||||
# via sendgrid
|
# via sendgrid
|
||||||
structlog==21.5.0
|
structlog==23.1.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
swapper==1.3.0
|
swapper==1.3.0
|
||||||
# via django-notifications-hq
|
# via django-notifications-hq
|
||||||
telepath==0.2
|
telepath==0.3.1
|
||||||
# via wagtail
|
# via wagtail
|
||||||
text-unidecode==1.3
|
text-unidecode==1.3
|
||||||
# via
|
# via
|
||||||
# graphene-django
|
# graphene-django
|
||||||
# python-slugify
|
# python-slugify
|
||||||
typing-extensions==4.5.0
|
typing-extensions==4.7.1
|
||||||
# via
|
# via
|
||||||
|
# asgiref
|
||||||
# azure-core
|
# azure-core
|
||||||
# azure-storage-blob
|
# azure-storage-blob
|
||||||
|
# dj-database-url
|
||||||
|
# uvicorn
|
||||||
# wagtail-localize
|
# wagtail-localize
|
||||||
uritemplate==4.1.1
|
uritemplate==4.1.1
|
||||||
# via drf-spectacular
|
# via drf-spectacular
|
||||||
urllib3==1.26.9
|
urllib3==1.26.16
|
||||||
# via
|
# via
|
||||||
# botocore
|
# botocore
|
||||||
# requests
|
# requests
|
||||||
# sentry-sdk
|
# sentry-sdk
|
||||||
uvicorn[standard]==0.18.3
|
uvicorn[standard]==0.23.2
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
uvloop==0.16.0
|
uvloop==0.17.0
|
||||||
# via uvicorn
|
# via uvicorn
|
||||||
wagtail==4.2.2
|
wagtail==5.1
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# wagtail-factories
|
# wagtail-factories
|
||||||
# wagtail-grapple
|
# wagtail-grapple
|
||||||
# wagtail-headless-preview
|
# wagtail-headless-preview
|
||||||
# wagtail-localize
|
# wagtail-localize
|
||||||
wagtail-factories==4.0.0
|
wagtail-factories==4.1.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
wagtail-grapple==0.19.2
|
wagtail-grapple==0.20.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
wagtail-headless-preview==0.4.0
|
wagtail-headless-preview==0.6.0
|
||||||
# via wagtail-grapple
|
# via wagtail-grapple
|
||||||
wagtail-localize==1.5
|
wagtail-localize==1.5.1
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
watchfiles==0.17.0
|
watchfiles==0.19.0
|
||||||
# via uvicorn
|
# via uvicorn
|
||||||
webencodings==0.5.1
|
webencodings==0.5.1
|
||||||
# via html5lib
|
# via html5lib
|
||||||
websockets==10.2
|
websockets==11.0.3
|
||||||
# via uvicorn
|
# via uvicorn
|
||||||
whitenoise[brotli]==6.0.0
|
whitenoise[brotli]==6.5.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
willow==1.4.1
|
willow[heif]==1.6.1
|
||||||
# via wagtail
|
# via wagtail
|
||||||
wrapt==1.14.0
|
|
||||||
# via deprecated
|
|
||||||
|
|
||||||
# The following packages are considered to be unsafe in a requirements file:
|
|
||||||
# setuptools
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.template import loader
|
from django.template import loader
|
||||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||||
from ratelimit.decorators import ratelimit
|
from django_ratelimit.decorators import ratelimit
|
||||||
from rest_framework import authentication
|
from rest_framework import authentication
|
||||||
from rest_framework.decorators import (
|
from rest_framework.decorators import (
|
||||||
api_view,
|
api_view,
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ from vbv_lernwelt.learnpath.tests.learning_path_factories import (
|
||||||
CircleFactory,
|
CircleFactory,
|
||||||
LearningContentAssignmentFactory,
|
LearningContentAssignmentFactory,
|
||||||
LearningContentAttendanceCourseFactory,
|
LearningContentAttendanceCourseFactory,
|
||||||
|
LearningContentEdoniqTestFactory,
|
||||||
LearningContentFeedbackFactory,
|
LearningContentFeedbackFactory,
|
||||||
LearningContentLearningModuleFactory,
|
LearningContentLearningModuleFactory,
|
||||||
LearningContentMediaLibraryFactory,
|
LearningContentMediaLibraryFactory,
|
||||||
|
|
@ -309,6 +310,16 @@ damit du erfolgreich mit deinem Lernpfad (durch-)starten kannst.
|
||||||
slug__startswith="test-lehrgang-assignment-fahrzeug-mein-erstes-auto"
|
slug__startswith="test-lehrgang-assignment-fahrzeug-mein-erstes-auto"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
LearningContentEdoniqTestFactory(
|
||||||
|
title="Wissens- und Verständnisfragen",
|
||||||
|
parent=circle,
|
||||||
|
description=RichText(
|
||||||
|
"<p>Folgender Test mit Wissens- und Verständnisfragen ist Teil des Kompetenznachweises. Der Test kann nur einmal durchgeführt werden und ist notenrelevant.</p>"
|
||||||
|
),
|
||||||
|
checkbox_text="Hiermit bestätige ich, dass ich die Anweisungen verstanden und die Redlichkeitserklärung akzeptiert habe.",
|
||||||
|
test_url="https://exam.vbv-afa.ch/e-tutor/v4/user/course/pre_course_object?aid=1689096897473,2147466097",
|
||||||
|
extended_time_test_url="https://exam2.vbv-afa.ch/e-tutor/v4/user/course/pre_course_object?aid=1689096897473,2147466097",
|
||||||
|
)
|
||||||
|
|
||||||
PerformanceCriteriaFactory(
|
PerformanceCriteriaFactory(
|
||||||
parent=CompetencePage.objects.get(competence_id="X1"),
|
parent=CompetencePage.objects.get(competence_id="X1"),
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@ from vbv_lernwelt.learnpath.tests.learning_path_factories import (
|
||||||
LearningContentAssignmentFactory,
|
LearningContentAssignmentFactory,
|
||||||
LearningContentAttendanceCourseFactory,
|
LearningContentAttendanceCourseFactory,
|
||||||
LearningContentDocumentListFactory,
|
LearningContentDocumentListFactory,
|
||||||
|
LearningContentEdoniqTestFactory,
|
||||||
LearningContentFeedbackFactory,
|
LearningContentFeedbackFactory,
|
||||||
LearningContentMediaLibraryFactory,
|
LearningContentMediaLibraryFactory,
|
||||||
LearningContentPlaceholderFactory,
|
LearningContentPlaceholderFactory,
|
||||||
LearningContentTestFactory,
|
|
||||||
LearningPathFactory,
|
LearningPathFactory,
|
||||||
LearningSequenceFactory,
|
LearningSequenceFactory,
|
||||||
LearningUnitFactory,
|
LearningUnitFactory,
|
||||||
|
|
@ -329,14 +329,14 @@ In diesem Circle erfährst du wie die überbetrieblichen Kurse aufgebaut sind. Z
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
LearningUnitFactory(title="Kompetenznachweis", title_hidden=True, parent=circle)
|
LearningUnitFactory(title="Kompetenznachweis", title_hidden=True, parent=circle)
|
||||||
LearningContentTestFactory(
|
LearningContentEdoniqTestFactory(
|
||||||
title="Wissens- und Verständnisfragen",
|
title="Wissens- und Verständnisfragen",
|
||||||
parent=circle,
|
parent=circle,
|
||||||
description=RichText(
|
description=RichText(
|
||||||
"<p>Folgender Test mit Wissens- und Verständnisfragen ist Teil des Kompetenznachweises. Der Test kann nur einmal durchgeführt werden und ist notenrelevant.</p>"
|
"<p>Folgender Test mit Wissens- und Verständnisfragen ist Teil des Kompetenznachweises. Der Test kann nur einmal durchgeführt werden und ist notenrelevant.</p>"
|
||||||
),
|
),
|
||||||
checkbox_text="Hiermit bestätige ich, dass ich die Anweisungen verstanden habe und den Test durchführen möchte.",
|
checkbox_text="Hiermit bestätige ich, dass ich die Anweisungen verstanden und die Redlichkeitserklärung akzeptiert habe.",
|
||||||
content_url="https://exam.vbv-afa.ch/",
|
test_url="https://exam.vbv-afa.ch/e-tutor/v4/user/course/pre_course_object?aid=1689096897473,2147466097",
|
||||||
)
|
)
|
||||||
LearningUnitFactory(title="Feedback", title_hidden=True, parent=circle)
|
LearningUnitFactory(title="Feedback", title_hidden=True, parent=circle)
|
||||||
LearningContentFeedbackFactory(
|
LearningContentFeedbackFactory(
|
||||||
|
|
@ -444,14 +444,14 @@ Dans ce cercle, tu apprendras comment les cours interentreprises sont structuré
|
||||||
LearningUnitFactory(
|
LearningUnitFactory(
|
||||||
title="Contrôle de compétences", title_hidden=True, parent=circle
|
title="Contrôle de compétences", title_hidden=True, parent=circle
|
||||||
)
|
)
|
||||||
LearningContentTestFactory(
|
LearningContentEdoniqTestFactory(
|
||||||
title="Questions de connaissances et de compréhension",
|
title="Questions de connaissances et de compréhension",
|
||||||
parent=circle,
|
parent=circle,
|
||||||
description=RichText(
|
description=RichText(
|
||||||
"<p>Folgender Test mit Wissens- und Verständnisfragen ist Teil des Kompetenznachweises. Der Test kann nur einmal durchgeführt werden und ist notenrelevant.</p>"
|
"<p>Folgender Test mit Wissens- und Verständnisfragen ist Teil des Kompetenznachweises. Der Test kann nur einmal durchgeführt werden und ist notenrelevant.</p>"
|
||||||
),
|
),
|
||||||
checkbox_text="Hiermit bestätige ich, dass ich die Anweisungen verstanden habe und den Test durchführen möchte.",
|
checkbox_text="Hiermit bestätige ich, dass ich die Anweisungen verstanden und die Redlichkeitserklärung akzeptiert habe.",
|
||||||
content_url="https://exam.vbv-afa.ch/",
|
test_url="https://exam.vbv-afa.ch/e-tutor/v4/user/course/pre_course_object?aid=1689096897473,2147466097",
|
||||||
)
|
)
|
||||||
LearningUnitFactory(title="Feedback", title_hidden=True, parent=circle)
|
LearningUnitFactory(title="Feedback", title_hidden=True, parent=circle)
|
||||||
LearningContentFeedbackFactory(
|
LearningContentFeedbackFactory(
|
||||||
|
|
@ -559,14 +559,14 @@ In questo Circle imparerai come sono strutturati i corsi interaziendali. Imparer
|
||||||
LearningUnitFactory(
|
LearningUnitFactory(
|
||||||
title="Controllo delle competenze", title_hidden=True, parent=circle
|
title="Controllo delle competenze", title_hidden=True, parent=circle
|
||||||
)
|
)
|
||||||
LearningContentTestFactory(
|
LearningContentEdoniqTestFactory(
|
||||||
title="Domande di conoscenza e di comprensione",
|
title="Domande di conoscenza e di comprensione",
|
||||||
parent=circle,
|
parent=circle,
|
||||||
description=RichText(
|
description=RichText(
|
||||||
"<p>Folgender Test mit Wissens- und Verständnisfragen ist Teil des Kompetenznachweises. Der Test kann nur einmal durchgeführt werden und ist notenrelevant.</p>"
|
"<p>Folgender Test mit Wissens- und Verständnisfragen ist Teil des Kompetenznachweises. Der Test kann nur einmal durchgeführt werden und ist notenrelevant.</p>"
|
||||||
),
|
),
|
||||||
checkbox_text="Hiermit bestätige ich, dass ich die Anweisungen verstanden habe und den Test durchführen möchte.",
|
checkbox_text="Hiermit bestätige ich, dass ich die Anweisungen verstanden und die Redlichkeitserklärung akzeptiert habe.",
|
||||||
content_url="https://exam.vbv-afa.ch/",
|
test_url="https://exam.vbv-afa.ch/e-tutor/v4/user/course/pre_course_object?aid=1689096897473,2147466097",
|
||||||
)
|
)
|
||||||
LearningUnitFactory(title="Feedback", title_hidden=True, parent=circle)
|
LearningUnitFactory(title="Feedback", title_hidden=True, parent=circle)
|
||||||
LearningContentFeedbackFactory(
|
LearningContentFeedbackFactory(
|
||||||
|
|
@ -679,14 +679,15 @@ In diesem Circle lernst du die wichtigsten Grundlagen bezüglich Versicherungswi
|
||||||
)
|
)
|
||||||
LearningSequenceFactory(title="Transfer", parent=circle, icon="it-icon-ls-end")
|
LearningSequenceFactory(title="Transfer", parent=circle, icon="it-icon-ls-end")
|
||||||
LearningUnitFactory(title="Kompetenznachweis", title_hidden=True, parent=circle)
|
LearningUnitFactory(title="Kompetenznachweis", title_hidden=True, parent=circle)
|
||||||
LearningContentTestFactory(
|
LearningContentEdoniqTestFactory(
|
||||||
title="Wissens- und Verständnisfragen",
|
title="Wissens- und Verständnisfragen",
|
||||||
parent=circle,
|
parent=circle,
|
||||||
description=RichText(
|
description=RichText(
|
||||||
"<p>Folgender Test mit Wissens- und Verständnisfragen ist Teil des Kompetenznachweises. Der Test kann nur einmal durchgeführt werden und ist notenrelevant.</p>"
|
"<p>Folgender Test mit Wissens- und Verständnisfragen ist Teil des Kompetenznachweises. Der Test kann nur einmal durchgeführt werden und ist notenrelevant.</p>"
|
||||||
),
|
),
|
||||||
checkbox_text="Hiermit bestätige ich, dass ich die Anweisungen verstanden habe und den Test durchführen möchte.",
|
checkbox_text="Hiermit bestätige ich, dass ich die Anweisungen verstanden und die Redlichkeitserklärung akzeptiert habe.",
|
||||||
content_url="https://exam.vbv-afa.ch/",
|
test_url="https://exam.vbv-afa.ch/e-tutor/v4/user/course/pre_course_object?aid=1689096523730,2147466125",
|
||||||
|
extended_time_test_url="https://exam.vbv-afa.ch/e-tutor/v4/user/course/pre_course_object?aid=1691157696911,2147478636",
|
||||||
)
|
)
|
||||||
LearningUnitFactory(title="Reflexion", title_hidden=True, parent=circle)
|
LearningUnitFactory(title="Reflexion", title_hidden=True, parent=circle)
|
||||||
LearningContentAssignmentFactory(
|
LearningContentAssignmentFactory(
|
||||||
|
|
@ -787,14 +788,15 @@ Dans ce cercle, tu apprends les bases les plus importantes en matière d'assuran
|
||||||
LearningUnitFactory(
|
LearningUnitFactory(
|
||||||
title="Contrôle de compétences", title_hidden=True, parent=circle
|
title="Contrôle de compétences", title_hidden=True, parent=circle
|
||||||
)
|
)
|
||||||
LearningContentTestFactory(
|
LearningContentEdoniqTestFactory(
|
||||||
title="Questions de connaissances et de compréhension",
|
title="Questions de connaissances et de compréhension",
|
||||||
parent=circle,
|
parent=circle,
|
||||||
description=RichText(
|
description=RichText(
|
||||||
"<p>Folgender Test mit Wissens- und Verständnisfragen ist Teil des Kompetenznachweises. Der Test kann nur einmal durchgeführt werden und ist notenrelevant.</p>"
|
"<p>Folgender Test mit Wissens- und Verständnisfragen ist Teil des Kompetenznachweises. Der Test kann nur einmal durchgeführt werden und ist notenrelevant.</p>"
|
||||||
),
|
),
|
||||||
checkbox_text="Hiermit bestätige ich, dass ich die Anweisungen verstanden habe und den Test durchführen möchte.",
|
checkbox_text="Hiermit bestätige ich, dass ich die Anweisungen verstanden und die Redlichkeitserklärung akzeptiert habe.",
|
||||||
content_url="https://exam.vbv-afa.ch/",
|
test_url="https://exam.vbv-afa.ch/e-tutor/v4/user/course/pre_course_object?aid=1689096523730,2147466125",
|
||||||
|
extended_time_test_url="https://exam.vbv-afa.ch/e-tutor/v4/user/course/pre_course_object?aid=1691157696911,2147478636",
|
||||||
)
|
)
|
||||||
LearningUnitFactory(title="Réflexion", title_hidden=True, parent=circle)
|
LearningUnitFactory(title="Réflexion", title_hidden=True, parent=circle)
|
||||||
LearningContentAssignmentFactory(
|
LearningContentAssignmentFactory(
|
||||||
|
|
@ -895,14 +897,15 @@ In questo Circle imparerai le basi più importanti del settore assicurativo e de
|
||||||
LearningUnitFactory(
|
LearningUnitFactory(
|
||||||
title="Controllo delle competenze", title_hidden=True, parent=circle
|
title="Controllo delle competenze", title_hidden=True, parent=circle
|
||||||
)
|
)
|
||||||
LearningContentTestFactory(
|
LearningContentEdoniqTestFactory(
|
||||||
title="Domande di conoscenza e di comprensione",
|
title="Domande di conoscenza e di comprensione",
|
||||||
parent=circle,
|
parent=circle,
|
||||||
description=RichText(
|
description=RichText(
|
||||||
"<p>Folgender Test mit Wissens- und Verständnisfragen ist Teil des Kompetenznachweises. Der Test kann nur einmal durchgeführt werden und ist notenrelevant.</p>"
|
"<p>Folgender Test mit Wissens- und Verständnisfragen ist Teil des Kompetenznachweises. Der Test kann nur einmal durchgeführt werden und ist notenrelevant.</p>"
|
||||||
),
|
),
|
||||||
checkbox_text="Hiermit bestätige ich, dass ich die Anweisungen verstanden habe und den Test durchführen möchte.",
|
checkbox_text="Hiermit bestätige ich, dass ich die Anweisungen verstanden und die Redlichkeitserklärung akzeptiert habe.",
|
||||||
content_url="https://exam.vbv-afa.ch/",
|
test_url="https://exam.vbv-afa.ch/e-tutor/v4/user/course/pre_course_object?aid=1689096523730,2147466125",
|
||||||
|
extended_time_test_url="https://exam.vbv-afa.ch/e-tutor/v4/user/course/pre_course_object?aid=1691157696911,2147478636",
|
||||||
)
|
)
|
||||||
LearningUnitFactory(title="Riflessione", title_hidden=True, parent=circle)
|
LearningUnitFactory(title="Riflessione", title_hidden=True, parent=circle)
|
||||||
LearningContentAssignmentFactory(
|
LearningContentAssignmentFactory(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Generated by Django 3.2.20 on 2023-08-17 13:14
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("learnpath", "0003_auto_20230810_0817"),
|
||||||
|
("course", "0003_alter_coursecompletion_additional_json_data"),
|
||||||
|
("duedate", "0002_alter_duedate_start"),
|
||||||
|
("course_session", "0003_initial"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="CourseSessionEdoniqTest",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"course_session",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to="course.coursesession",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"due_date",
|
||||||
|
models.OneToOneField(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="edoniq_test_due_date",
|
||||||
|
to="duedate.duedate",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"learning_content",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to="learnpath.learningcontentedoniqtest",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -152,3 +152,22 @@ class CourseSessionAssignment(models.Model):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.course_session} - {self.learning_content}"
|
return f"{self.course_session} - {self.learning_content}"
|
||||||
|
|
||||||
|
|
||||||
|
class CourseSessionEdoniqTest(models.Model):
|
||||||
|
course_session = models.ForeignKey(
|
||||||
|
"course.CourseSession",
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
learning_content = models.ForeignKey(
|
||||||
|
"learnpath.LearningContentEdoniqTest",
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
due_date = models.OneToOneField(
|
||||||
|
"duedate.DueDate",
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
related_name="edoniq_test_due_date",
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.course_session} - {self.learning_content}"
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ from wagtail.models import Page
|
||||||
from vbv_lernwelt.duedate.models import DueDate
|
from vbv_lernwelt.duedate.models import DueDate
|
||||||
from vbv_lernwelt.learnpath.models import (
|
from vbv_lernwelt.learnpath.models import (
|
||||||
LearningContentAttendanceCourse,
|
LearningContentAttendanceCourse,
|
||||||
LearningContentTest,
|
LearningContentEdoniqTest,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -23,7 +23,7 @@ class DueDateAdmin(admin.ModelAdmin):
|
||||||
csd = DueDate.objects.get(id=object_id)
|
csd = DueDate.objects.get(id=object_id)
|
||||||
kwargs["queryset"] = Page.objects.descendant_of(
|
kwargs["queryset"] = Page.objects.descendant_of(
|
||||||
csd.course_session.course.coursepage
|
csd.course_session.course.coursepage
|
||||||
).exact_type(LearningContentAttendanceCourse, LearningContentTest)
|
).exact_type(LearningContentAttendanceCourse, LearningContentEdoniqTest)
|
||||||
else:
|
else:
|
||||||
kwargs["queryset"] = Page.objects.none()
|
kwargs["queryset"] = Page.objects.none()
|
||||||
return super().formfield_for_foreignkey(db_field, request, **kwargs)
|
return super().formfield_for_foreignkey(db_field, request, **kwargs)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Generated by Django 3.2.20 on 2023-08-17 13:14
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("duedate", "0001_initial"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="duedate",
|
||||||
|
name="start",
|
||||||
|
field=models.DateTimeField(blank=True, db_index=True, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class LearnpathConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
|
||||||
|
name = "vbv_lernwelt.edoniq_test"
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
import base64
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import structlog
|
||||||
|
from Crypto.Cipher import PKCS1_v1_5
|
||||||
|
from Crypto.PublicKey import RSA
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
CIPHER_TRANSFORMATION = "RSA/ECB/PKCS1Padding"
|
||||||
|
|
||||||
|
|
||||||
|
def create_token(user_id: str):
|
||||||
|
try:
|
||||||
|
token = (
|
||||||
|
f"user:{user_id};system:{settings.EDONIQ_ENV};date:"
|
||||||
|
+ str(int(datetime.now().timestamp()))
|
||||||
|
+ ";"
|
||||||
|
)
|
||||||
|
|
||||||
|
encrypted = _encrypt_message(
|
||||||
|
token, settings.EDONIQ_CERTIFICATE.replace("\\n", "\n")
|
||||||
|
)
|
||||||
|
return str(base64.b64encode(encrypted), "utf-8")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(
|
||||||
|
"get_edoniq_test_fail",
|
||||||
|
label="edoniq_test_api",
|
||||||
|
error=e,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _encrypt_message(token: str, key: str):
|
||||||
|
key = RSA.import_key(key)
|
||||||
|
plainbytes = token.encode("utf-8")
|
||||||
|
cipherbytes = _encrypt(plainbytes, key)
|
||||||
|
encrypted_token = base64.b64encode(cipherbytes)
|
||||||
|
return encrypted_token
|
||||||
|
|
||||||
|
|
||||||
|
def _encrypt(token, key):
|
||||||
|
cipher = PKCS1_v1_5.new(key)
|
||||||
|
return cipher.encrypt(token)
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
from rest_framework.test import APITestCase
|
||||||
|
|
||||||
|
from vbv_lernwelt.core.create_default_users import create_default_users
|
||||||
|
from vbv_lernwelt.course.creators.test_course import create_test_course
|
||||||
|
from vbv_lernwelt.learnpath.models import LearningContentEdoniqTest
|
||||||
|
|
||||||
|
|
||||||
|
class RedirectTestCase(APITestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
create_default_users()
|
||||||
|
create_test_course(with_sessions=True)
|
||||||
|
|
||||||
|
def test_redirects_normal_test(self):
|
||||||
|
test = LearningContentEdoniqTest.objects.get(
|
||||||
|
title="Wissens- und Verständnisfragen"
|
||||||
|
)
|
||||||
|
data = {"learning_content_id": test.id, "extended_time_test": False}
|
||||||
|
self.client.login(username="admin", password="test")
|
||||||
|
self._test_redirect(
|
||||||
|
data,
|
||||||
|
"https://exam.vbv-afa.ch/e-tutor/v4/user/course/pre_course_object?aid=1689096897473,2147466097",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_redirects_extended_test(self):
|
||||||
|
test = LearningContentEdoniqTest.objects.get(
|
||||||
|
title="Wissens- und Verständnisfragen"
|
||||||
|
)
|
||||||
|
data = {"learning_content_id": test.id, "extended_time_test": True}
|
||||||
|
self.client.login(username="admin", password="test")
|
||||||
|
self._test_redirect(
|
||||||
|
data,
|
||||||
|
"https://exam2.vbv-afa.ch/e-tutor/v4/user/course/pre_course_object?aid=1689096897473,2147466097",
|
||||||
|
)
|
||||||
|
|
||||||
|
def _test_redirect(self, data, expected_url):
|
||||||
|
response = self.client.post(
|
||||||
|
"/api/core/edoniq-test/redirect/", data, format="json"
|
||||||
|
)
|
||||||
|
self.assertEqual(200, response.status_code)
|
||||||
|
content = response.json()
|
||||||
|
self.assertTrue(content["redirect_url"].startswith(expected_url))
|
||||||
|
|
@ -1,3 +1,14 @@
|
||||||
|
import structlog
|
||||||
|
from django.core.exceptions import PermissionDenied
|
||||||
|
from django.http import JsonResponse
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
from rest_framework.decorators import api_view
|
||||||
|
|
||||||
|
from vbv_lernwelt.course.permissions import has_course_access_by_page_request
|
||||||
|
from vbv_lernwelt.edoniq_test.edoniq_sso import create_token
|
||||||
|
from vbv_lernwelt.learnpath.models import LearningContentEdoniqTest
|
||||||
|
|
||||||
|
logger = structlog.get_logger(__name__)
|
||||||
import csv
|
import csv
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
@ -15,6 +26,62 @@ UK_COURSE_IDS = [COURSE_UK, COURSE_UK_FR, COURSE_UK_IT]
|
||||||
DEFAULT_EXCLUDED_DOMAINS = ["eiger-versicherung.ch", "assurance.ch", "example.com"]
|
DEFAULT_EXCLUDED_DOMAINS = ["eiger-versicherung.ch", "assurance.ch", "example.com"]
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(["POST"])
|
||||||
|
def get_edoniq_token_redirect(request):
|
||||||
|
page_id = request.data.get("learning_content_id", "")
|
||||||
|
extended_time_test = request.data.get("extended_time_test", False)
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
"get_edoniq_test_redirect",
|
||||||
|
label="edoniq_test_api",
|
||||||
|
page_id=page_id,
|
||||||
|
user_id=request.user.id,
|
||||||
|
extended_time_test=extended_time_test,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not page_id:
|
||||||
|
return JsonResponse({"error": "learning_content_id is required"}, status=400)
|
||||||
|
|
||||||
|
try:
|
||||||
|
test_page = get_object_or_404(LearningContentEdoniqTest, id=page_id)
|
||||||
|
|
||||||
|
if not has_course_access_by_page_request(request, test_page):
|
||||||
|
logger.debug(
|
||||||
|
"get_edoniq_test_redirect_permission_denied",
|
||||||
|
label="edoniq_test_api",
|
||||||
|
page_id=page_id,
|
||||||
|
page_slug=test_page.slug,
|
||||||
|
page_title=test_page.title,
|
||||||
|
user_id=request.user.id,
|
||||||
|
)
|
||||||
|
raise PermissionDenied()
|
||||||
|
|
||||||
|
url = (
|
||||||
|
test_page.test_url
|
||||||
|
if not extended_time_test
|
||||||
|
else test_page.extended_time_test_url
|
||||||
|
)
|
||||||
|
token = create_token(
|
||||||
|
str(request.user.id),
|
||||||
|
)
|
||||||
|
redirect_url = f"{url}&ssoToken={token}"
|
||||||
|
response_data = {"redirect_url": redirect_url}
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
"get_edoniq_test_redirect_permission_success",
|
||||||
|
label="edoniq_test_api",
|
||||||
|
page_id=page_id,
|
||||||
|
page_slug=test_page.slug,
|
||||||
|
page_title=test_page.title,
|
||||||
|
user_id=request.user.id,
|
||||||
|
)
|
||||||
|
return JsonResponse(response_data, status=200)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e, exc_info=True)
|
||||||
|
return JsonResponse({"error": str(e)}, status=404)
|
||||||
|
|
||||||
|
|
||||||
@staff_member_required
|
@staff_member_required
|
||||||
def export_students(request):
|
def export_students(request):
|
||||||
course_session_users = fetch_course_session_users(UK_COURSE_IDS)
|
course_session_users = fetch_course_session_users(UK_COURSE_IDS)
|
||||||
|
|
@ -35,6 +102,14 @@ def export_students_and_trainers(request):
|
||||||
return generate_export_response(course_session_users)
|
return generate_export_response(course_session_users)
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_course_session_users(courses: List[int]):
|
||||||
|
# if a user is in multiple courses, he should be exported multiple times
|
||||||
|
# todo: check if this is the case otherwise use .distinct("user")
|
||||||
|
return CourseSessionUser.objects.filter(
|
||||||
|
course_session__course__id__in=courses, role=CourseSessionUser.Role.MEMBER
|
||||||
|
).order_by("user__email")
|
||||||
|
|
||||||
|
|
||||||
def fetch_course_session_users(
|
def fetch_course_session_users(
|
||||||
courses: List[int], role=CourseSessionUser.Role.MEMBER, excluded_domains=None
|
courses: List[int], role=CourseSessionUser.Role.MEMBER, excluded_domains=None
|
||||||
):
|
):
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,12 @@ from vbv_lernwelt.course.models import CourseCategory, CoursePage
|
||||||
from vbv_lernwelt.learnpath.tests.learning_path_factories import (
|
from vbv_lernwelt.learnpath.tests.learning_path_factories import (
|
||||||
CircleFactory,
|
CircleFactory,
|
||||||
LearningContentAssignmentFactory,
|
LearningContentAssignmentFactory,
|
||||||
|
LearningContentEdoniqTestFactory,
|
||||||
LearningContentFeedbackFactory,
|
LearningContentFeedbackFactory,
|
||||||
LearningContentLearningModuleFactory,
|
LearningContentLearningModuleFactory,
|
||||||
LearningContentMediaLibraryFactory,
|
LearningContentMediaLibraryFactory,
|
||||||
LearningContentPlaceholderFactory,
|
LearningContentPlaceholderFactory,
|
||||||
LearningContentRichTextFactory,
|
LearningContentRichTextFactory,
|
||||||
LearningContentTestFactory,
|
|
||||||
LearningContentVideoFactory,
|
LearningContentVideoFactory,
|
||||||
LearningPathFactory,
|
LearningPathFactory,
|
||||||
LearningSequenceFactory,
|
LearningSequenceFactory,
|
||||||
|
|
@ -353,13 +353,13 @@ def create_circle_fahrzeug(lp, title="Fahrzeug"):
|
||||||
title="Praxisauftrag",
|
title="Praxisauftrag",
|
||||||
parent=circle,
|
parent=circle,
|
||||||
)
|
)
|
||||||
LearningContentTestFactory(
|
LearningContentEdoniqTestFactory(
|
||||||
title="Fachcheck Fahrzeug",
|
title="Fachcheck Fahrzeug",
|
||||||
parent=circle,
|
parent=circle,
|
||||||
description=RichText(
|
description=RichText(
|
||||||
"<p>Teste dein Wissen mit dem Fachcheck. Der Test kann nur einmal durchgeführt werden.</p>"
|
"<p>Teste dein Wissen mit dem Fachcheck. Der Test kann nur einmal durchgeführt werden.</p>"
|
||||||
),
|
),
|
||||||
checkbox_text="Hiermit bestätige ich, dass ich die Anweisungen verstanden habe und den Test durchführen möchte.",
|
checkbox_text="Hiermit bestätige ich, dass ich die Anweisungen verstanden und die Redlichkeitserklärung akzeptiert habe.",
|
||||||
content_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/fachcheck-fahrzeug-xapi-LFv8YiyM/index.html#/",
|
content_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/fachcheck-fahrzeug-xapi-LFv8YiyM/index.html#/",
|
||||||
)
|
)
|
||||||
LearningContentAssignmentFactory(
|
LearningContentAssignmentFactory(
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,12 @@ from vbv_lernwelt.learnpath.models import (
|
||||||
LearningContentAssignment,
|
LearningContentAssignment,
|
||||||
LearningContentAttendanceCourse,
|
LearningContentAttendanceCourse,
|
||||||
LearningContentDocumentList,
|
LearningContentDocumentList,
|
||||||
|
LearningContentEdoniqTest,
|
||||||
LearningContentFeedback,
|
LearningContentFeedback,
|
||||||
LearningContentLearningModule,
|
LearningContentLearningModule,
|
||||||
LearningContentMediaLibrary,
|
LearningContentMediaLibrary,
|
||||||
LearningContentPlaceholder,
|
LearningContentPlaceholder,
|
||||||
LearningContentRichText,
|
LearningContentRichText,
|
||||||
LearningContentTest,
|
|
||||||
LearningContentVideo,
|
LearningContentVideo,
|
||||||
LearningPath,
|
LearningPath,
|
||||||
LearningSequence,
|
LearningSequence,
|
||||||
|
|
@ -46,7 +46,7 @@ class LearningContentInterface(CoursePageInterface):
|
||||||
return LearningContentPlaceholderObjectType
|
return LearningContentPlaceholderObjectType
|
||||||
elif isinstance(instance, LearningContentRichText):
|
elif isinstance(instance, LearningContentRichText):
|
||||||
return LearningContentRichTextObjectType
|
return LearningContentRichTextObjectType
|
||||||
elif isinstance(instance, LearningContentTest):
|
elif isinstance(instance, LearningContentEdoniqTest):
|
||||||
return LearningContentTestObjectType
|
return LearningContentTestObjectType
|
||||||
elif isinstance(instance, LearningContentVideo):
|
elif isinstance(instance, LearningContentVideo):
|
||||||
return LearningContentVideoObjectType
|
return LearningContentVideoObjectType
|
||||||
|
|
@ -104,7 +104,7 @@ class LearningContentMediaLibraryObjectType(DjangoObjectType):
|
||||||
|
|
||||||
class LearningContentTestObjectType(DjangoObjectType):
|
class LearningContentTestObjectType(DjangoObjectType):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = LearningContentTest
|
model = LearningContentEdoniqTest
|
||||||
interfaces = (LearningContentInterface,)
|
interfaces = (LearningContentInterface,)
|
||||||
fields = []
|
fields = []
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
# Generated by Django 3.2.13 on 2023-08-10 06:17
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
import wagtail.fields
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("course", "0003_alter_coursecompletion_additional_json_data"),
|
||||||
|
("wagtailcore", "0083_workflowcontenttype"),
|
||||||
|
("wagtailredirects", "0008_add_verbose_name_plural"),
|
||||||
|
("wagtailforms", "0005_alter_formsubmission_form_data"),
|
||||||
|
("duedate", "0001_initial"),
|
||||||
|
("learnpath", "0002_alter_learningcontentassignment_assignment_type"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="LearningContentEdoniqTest",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"page_ptr",
|
||||||
|
models.OneToOneField(
|
||||||
|
auto_created=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
parent_link=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
to="wagtailcore.page",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("minutes", models.PositiveIntegerField(default=15)),
|
||||||
|
("description", wagtail.fields.RichTextField(blank=True)),
|
||||||
|
("content_url", models.TextField(blank=True)),
|
||||||
|
("has_course_completion_status", models.BooleanField(default=True)),
|
||||||
|
(
|
||||||
|
"can_user_self_toggle_course_completion",
|
||||||
|
models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
("checkbox_text", models.TextField(blank=True)),
|
||||||
|
("test_url", models.TextField(blank=True)),
|
||||||
|
("extended_time_test_url", models.TextField(blank=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"abstract": False,
|
||||||
|
},
|
||||||
|
bases=("wagtailcore.page",),
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name="LearningContentTest",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -77,7 +77,7 @@ class Circle(CourseBasePage):
|
||||||
"learnpath.LearningContentMediaLibrary",
|
"learnpath.LearningContentMediaLibrary",
|
||||||
"learnpath.LearningContentPlaceholder",
|
"learnpath.LearningContentPlaceholder",
|
||||||
"learnpath.LearningContentRichText",
|
"learnpath.LearningContentRichText",
|
||||||
"learnpath.LearningContentTest",
|
"learnpath.LearningContentEdoniqTest",
|
||||||
"learnpath.LearningContentVideo",
|
"learnpath.LearningContentVideo",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -321,19 +321,28 @@ class LearningContentMediaLibrary(LearningContent):
|
||||||
can_user_self_toggle_course_completion = models.BooleanField(default=True)
|
can_user_self_toggle_course_completion = models.BooleanField(default=True)
|
||||||
|
|
||||||
|
|
||||||
class LearningContentTest(LearningContent):
|
class LearningContentEdoniqTest(LearningContent):
|
||||||
serialize_field_names = LearningContent.serialize_field_names + [
|
serialize_field_names = LearningContent.serialize_field_names + [
|
||||||
"checkbox_text",
|
"checkbox_text",
|
||||||
|
"has_extended_time_test",
|
||||||
]
|
]
|
||||||
parent_page_types = ["learnpath.Circle"]
|
parent_page_types = ["learnpath.Circle"]
|
||||||
subpage_types = []
|
subpage_types = []
|
||||||
|
|
||||||
checkbox_text = models.TextField(blank=True)
|
checkbox_text = models.TextField(blank=True)
|
||||||
|
test_url = models.TextField(blank=True)
|
||||||
|
extended_time_test_url = models.TextField(blank=True)
|
||||||
|
|
||||||
content_panels = LearningContent.content_panels + [
|
content_panels = LearningContent.content_panels + [
|
||||||
FieldPanel("checkbox_text", classname="Text"),
|
FieldPanel("checkbox_text", classname="Text"),
|
||||||
|
FieldPanel("test_url", classname="Text"),
|
||||||
|
FieldPanel("extended_time_test_url", classname="Text"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_extended_time_test(self):
|
||||||
|
return bool(self.extended_time_test_url)
|
||||||
|
|
||||||
|
|
||||||
class LearningContentRichText(LearningContent):
|
class LearningContentRichText(LearningContent):
|
||||||
text = RichTextField(blank=True, features=DEFAULT_RICH_TEXT_FEATURES_WITH_HEADER)
|
text = RichTextField(blank=True, features=DEFAULT_RICH_TEXT_FEATURES_WITH_HEADER)
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,12 @@ from vbv_lernwelt.learnpath.models import (
|
||||||
LearningContentAssignment,
|
LearningContentAssignment,
|
||||||
LearningContentAttendanceCourse,
|
LearningContentAttendanceCourse,
|
||||||
LearningContentDocumentList,
|
LearningContentDocumentList,
|
||||||
|
LearningContentEdoniqTest,
|
||||||
LearningContentFeedback,
|
LearningContentFeedback,
|
||||||
LearningContentLearningModule,
|
LearningContentLearningModule,
|
||||||
LearningContentMediaLibrary,
|
LearningContentMediaLibrary,
|
||||||
LearningContentPlaceholder,
|
LearningContentPlaceholder,
|
||||||
LearningContentRichText,
|
LearningContentRichText,
|
||||||
LearningContentTest,
|
|
||||||
LearningContentVideo,
|
LearningContentVideo,
|
||||||
LearningPath,
|
LearningPath,
|
||||||
LearningSequence,
|
LearningSequence,
|
||||||
|
|
@ -149,14 +149,14 @@ class LearningContentMediaLibraryFactory(wagtail_factories.PageFactory):
|
||||||
model = LearningContentMediaLibrary
|
model = LearningContentMediaLibrary
|
||||||
|
|
||||||
|
|
||||||
class LearningContentTestFactory(wagtail_factories.PageFactory):
|
class LearningContentEdoniqTestFactory(wagtail_factories.PageFactory):
|
||||||
title = "Fachcheck"
|
title = "Fachcheck"
|
||||||
minutes = 0
|
minutes = 0
|
||||||
content_url = ""
|
content_url = ""
|
||||||
description = RichText("")
|
description = RichText("")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = LearningContentTest
|
model = LearningContentEdoniqTest
|
||||||
|
|
||||||
|
|
||||||
class LearningContentRichTextFactory(wagtail_factories.PageFactory):
|
class LearningContentRichTextFactory(wagtail_factories.PageFactory):
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ env/docker_local.env
|
||||||
server/vbv_lernwelt/assignment/creators/create_assignments.py
|
server/vbv_lernwelt/assignment/creators/create_assignments.py
|
||||||
server/vbv_lernwelt/static/
|
server/vbv_lernwelt/static/
|
||||||
server/vbv_lernwelt/media/
|
server/vbv_lernwelt/media/
|
||||||
|
server/vbv_lernwelt/edoniq_test/certificates/test.key
|
||||||
supabase.md
|
supabase.md
|
||||||
scripts/supabase/init.sql
|
scripts/supabase/init.sql
|
||||||
ramon.wenger@iterativ.ch.gpg
|
ramon.wenger@iterativ.ch.gpg
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue