diff --git a/docker-compose.yml b/docker-compose.yml index 34ef1ae0..1d6e257a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,7 +8,9 @@ services: - ${PRIVATE_FILES_PATH:-./private}:/app/private environment: - SECRET=${SECRET:-} + - DATA_FILES_PATH=/app/data - STATIC_FILES_PATH=/app/static + - PRIVATE_FILES_PATH=/app/private - DATABASE_PATH=/app/db - ENABLE_CORS=${ENABLE_CORS:-false} - HOST=${HOST:-backend} diff --git a/frontend/src/lib/client/services.gen.ts b/frontend/src/lib/client/services.gen.ts index 4fac64ce..88ad465d 100644 --- a/frontend/src/lib/client/services.gen.ts +++ b/frontend/src/lib/client/services.gen.ts @@ -1,7 +1,7 @@ // This file is auto-generated by @hey-api/openapi-ts -import { createClient, createConfig, type Options, formDataBodySerializer, urlSearchParamsBodySerializer } from '@hey-api/client-fetch'; -import type { GetLanguagesError, GetLanguagesResponse, GetMilestonesError, GetMilestonesResponse, GetMilestoneData, GetMilestoneError, GetMilestoneResponse, GetMilestoneGroupsData, GetMilestoneGroupsError, GetMilestoneGroupsResponse, GetUserQuestionsError, GetUserQuestionsResponse, GetChildQuestionsError, GetChildQuestionsResponse, CreateLanguageData, CreateLanguageError, CreateLanguageResponse, DeleteLanguageData, DeleteLanguageError, DeleteLanguageResponse, UpdateI18NData, UpdateI18NError, UpdateI18NResponse, GetMilestoneGroupsAdminError, GetMilestoneGroupsAdminResponse, CreateMilestoneGroupAdminError, CreateMilestoneGroupAdminResponse, UpdateMilestoneGroupAdminData, UpdateMilestoneGroupAdminError, UpdateMilestoneGroupAdminResponse, DeleteMilestoneGroupAdminData, DeleteMilestoneGroupAdminError, DeleteMilestoneGroupAdminResponse, UploadMilestoneGroupImageData, UploadMilestoneGroupImageError, UploadMilestoneGroupImageResponse, CreateMilestoneData, CreateMilestoneError, CreateMilestoneResponse, UpdateMilestoneData, UpdateMilestoneError, UpdateMilestoneResponse, DeleteMilestoneData, DeleteMilestoneError, DeleteMilestoneResponse, UploadMilestoneImageData, UploadMilestoneImageError, UploadMilestoneImageResponse, GetUserQuestionsAdminError, GetUserQuestionsAdminResponse, UpdateUserQuestionData, UpdateUserQuestionError, UpdateUserQuestionResponse, CreateUserQuestionError, CreateUserQuestionResponse, DeleteUserQuestionData, DeleteUserQuestionError, DeleteUserQuestionResponse, GetChildQuestionsAdminError, GetChildQuestionsAdminResponse, UpdateChildQuestionData, UpdateChildQuestionError, UpdateChildQuestionResponse, CreateChildQuestionError, CreateChildQuestionResponse, DeleteChildQuestionData, DeleteChildQuestionError, DeleteChildQuestionResponse, UsersCurrentUserError, UsersCurrentUserResponse, UsersPatchCurrentUserData, UsersPatchCurrentUserError, UsersPatchCurrentUserResponse, UsersUserData, UsersUserError, UsersUserResponse, UsersPatchUserData, UsersPatchUserError, UsersPatchUserResponse, UsersDeleteUserData, UsersDeleteUserError, UsersDeleteUserResponse, GetChildrenError, GetChildrenResponse, UpdateChildData, UpdateChildError, UpdateChildResponse, CreateChildData, CreateChildError, CreateChildResponse, GetChildData, GetChildError, GetChildResponse, DeleteChildData, DeleteChildError, DeleteChildResponse, GetChildImageData, GetChildImageError, GetChildImageResponse, UploadChildImageData, UploadChildImageError, UploadChildImageResponse, DeleteChildImageData, DeleteChildImageError, DeleteChildImageResponse, GetCurrentMilestoneAnswerSessionData, GetCurrentMilestoneAnswerSessionError, GetCurrentMilestoneAnswerSessionResponse, UpdateMilestoneAnswerData, UpdateMilestoneAnswerError, UpdateMilestoneAnswerResponse, GetCurrentUserAnswersError, GetCurrentUserAnswersResponse, UpdateCurrentUserAnswersData, UpdateCurrentUserAnswersError, UpdateCurrentUserAnswersResponse, GetCurrentChildAnswersData, GetCurrentChildAnswersError, GetCurrentChildAnswersResponse, UpdateCurrentChildAnswersData, UpdateCurrentChildAnswersError, UpdateCurrentChildAnswersResponse, AuthCookieLoginData, AuthCookieLoginError, AuthCookieLoginResponse, AuthCookieLogoutError, AuthCookieLogoutResponse, RegisterRegisterData, RegisterRegisterError, RegisterRegisterResponse, ResetForgotPasswordData, ResetForgotPasswordError, ResetForgotPasswordResponse, ResetResetPasswordData, ResetResetPasswordError, ResetResetPasswordResponse, VerifyRequestTokenData, VerifyRequestTokenError, VerifyRequestTokenResponse, VerifyVerifyData, VerifyVerifyError, VerifyVerifyResponse, AuthError, AuthResponse } from './types.gen'; +import { type Options, createClient, createConfig, formDataBodySerializer, urlSearchParamsBodySerializer } from '@hey-api/client-fetch'; +import type { AuthCookieLoginData, AuthCookieLoginError, AuthCookieLoginResponse, AuthCookieLogoutError, AuthCookieLogoutResponse, AuthError, AuthResponse, CreateChildData, CreateChildError, CreateChildQuestionError, CreateChildQuestionResponse, CreateChildResponse, CreateLanguageData, CreateLanguageError, CreateLanguageResponse, CreateMilestoneData, CreateMilestoneError, CreateMilestoneGroupAdminError, CreateMilestoneGroupAdminResponse, CreateMilestoneResponse, CreateUserQuestionError, CreateUserQuestionResponse, DeleteChildData, DeleteChildError, DeleteChildImageData, DeleteChildImageError, DeleteChildImageResponse, DeleteChildQuestionData, DeleteChildQuestionError, DeleteChildQuestionResponse, DeleteChildResponse, DeleteLanguageData, DeleteLanguageError, DeleteLanguageResponse, DeleteMilestoneData, DeleteMilestoneError, DeleteMilestoneGroupAdminData, DeleteMilestoneGroupAdminError, DeleteMilestoneGroupAdminResponse, DeleteMilestoneImageData, DeleteMilestoneImageError, DeleteMilestoneImageResponse, DeleteMilestoneResponse, DeleteUserQuestionData, DeleteUserQuestionError, DeleteUserQuestionResponse, GetChildData, GetChildError, GetChildImageData, GetChildImageError, GetChildImageResponse, GetChildQuestionsAdminError, GetChildQuestionsAdminResponse, GetChildQuestionsError, GetChildQuestionsResponse, GetChildResponse, GetChildrenError, GetChildrenResponse, GetCurrentChildAnswersData, GetCurrentChildAnswersError, GetCurrentChildAnswersResponse, GetCurrentMilestoneAnswerSessionData, GetCurrentMilestoneAnswerSessionError, GetCurrentMilestoneAnswerSessionResponse, GetCurrentUserAnswersError, GetCurrentUserAnswersResponse, GetLanguagesError, GetLanguagesResponse, GetMilestoneData, GetMilestoneError, GetMilestoneGroupsAdminError, GetMilestoneGroupsAdminResponse, GetMilestoneGroupsData, GetMilestoneGroupsError, GetMilestoneGroupsResponse, GetMilestoneResponse, GetMilestonesError, GetMilestonesResponse, GetUserQuestionsAdminError, GetUserQuestionsAdminResponse, GetUserQuestionsError, GetUserQuestionsResponse, RegisterRegisterData, RegisterRegisterError, RegisterRegisterResponse, ResetForgotPasswordData, ResetForgotPasswordError, ResetForgotPasswordResponse, ResetResetPasswordData, ResetResetPasswordError, ResetResetPasswordResponse, UpdateChildData, UpdateChildError, UpdateChildQuestionData, UpdateChildQuestionError, UpdateChildQuestionResponse, UpdateChildResponse, UpdateCurrentChildAnswersData, UpdateCurrentChildAnswersError, UpdateCurrentChildAnswersResponse, UpdateCurrentUserAnswersData, UpdateCurrentUserAnswersError, UpdateCurrentUserAnswersResponse, UpdateI18NData, UpdateI18NError, UpdateI18NResponse, UpdateMilestoneAnswerData, UpdateMilestoneAnswerError, UpdateMilestoneAnswerResponse, UpdateMilestoneData, UpdateMilestoneError, UpdateMilestoneGroupAdminData, UpdateMilestoneGroupAdminError, UpdateMilestoneGroupAdminResponse, UpdateMilestoneResponse, UpdateUserQuestionData, UpdateUserQuestionError, UpdateUserQuestionResponse, UploadChildImageData, UploadChildImageError, UploadChildImageResponse, UploadMilestoneGroupImageData, UploadMilestoneGroupImageError, UploadMilestoneGroupImageResponse, UploadMilestoneImageData, UploadMilestoneImageError, UploadMilestoneImageResponse, UsersCurrentUserError, UsersCurrentUserResponse, UsersDeleteUserData, UsersDeleteUserError, UsersDeleteUserResponse, UsersPatchCurrentUserData, UsersPatchCurrentUserError, UsersPatchCurrentUserResponse, UsersPatchUserData, UsersPatchUserError, UsersPatchUserResponse, UsersUserData, UsersUserError, UsersUserResponse, VerifyRequestTokenData, VerifyRequestTokenError, VerifyRequestTokenResponse, VerifyVerifyData, VerifyVerifyError, VerifyVerifyResponse } from './types.gen'; export const client = createClient(createConfig()); @@ -159,6 +159,14 @@ export const uploadMilestoneImage = (optio url: '/admin/milestone-images/{milestone_id}' }); }; +/** + * Delete Milestone Image + */ +export const deleteMilestoneImage = (options: Options) => { return (options?.client ?? client).delete({ + ...options, + url: '/admin/milestone-images/{milestone_image_id}' +}); }; + /** * Get User Questions Admin */ diff --git a/frontend/src/lib/client/types.gen.ts b/frontend/src/lib/client/types.gen.ts index a51c7657..eac88dbe 100644 --- a/frontend/src/lib/client/types.gen.ts +++ b/frontend/src/lib/client/types.gen.ts @@ -413,6 +413,16 @@ export type UploadMilestoneImageResponse = (MilestoneImage); export type UploadMilestoneImageError = (HTTPValidationError); +export type DeleteMilestoneImageData = { + path: { + milestone_image_id: number; + }; +}; + +export type DeleteMilestoneImageResponse = (unknown); + +export type DeleteMilestoneImageError = (HTTPValidationError); + export type GetUserQuestionsAdminResponse = (Array); export type GetUserQuestionsAdminError = unknown; diff --git a/frontend/src/lib/components/Admin/EditImage.svelte b/frontend/src/lib/components/Admin/EditImage.svelte new file mode 100644 index 00000000..32621564 --- /dev/null +++ b/frontend/src/lib/components/Admin/EditImage.svelte @@ -0,0 +1,23 @@ + + + + +
+{`${filename}`} + +
diff --git a/frontend/src/lib/components/Admin/EditMilestoneModal.svelte b/frontend/src/lib/components/Admin/EditMilestoneModal.svelte index a2997e35..72d9f551 100644 --- a/frontend/src/lib/components/Admin/EditMilestoneModal.svelte +++ b/frontend/src/lib/components/Admin/EditMilestoneModal.svelte @@ -3,12 +3,17 @@ - + {#if milestone} {#each textKeys as textKey} {@const title = $_(`admin.${textKey}`)} @@ -83,17 +108,17 @@ export async function saveChanges() {
- {#each milestone.images as milestoneImage, milestoneImageId (milestoneImage.id)} - {`${milestoneImageId}`} { + currentMilestoneImageId = milestoneImage.id; + showDeleteMilestoneImageModal = true; + }} /> {/each} {#each images as image} - milestone + milestone {/each}
{/if} - - + {open = false; saveChanges()}} /> + {open = false;}} /> + + diff --git a/frontend/src/lib/components/Admin/MilestoneGroups.svelte b/frontend/src/lib/components/Admin/MilestoneGroups.svelte index 9128e795..7b2fe86e 100644 --- a/frontend/src/lib/components/Admin/MilestoneGroups.svelte +++ b/frontend/src/lib/components/Admin/MilestoneGroups.svelte @@ -251,7 +251,7 @@ onMount(async () => { > {#key showEditMilestoneModal} - {/key} diff --git a/frontend/src/lib/components/Admin/Questions.svelte b/frontend/src/lib/components/Admin/Questions.svelte index 24493ed6..78b73462 100644 --- a/frontend/src/lib/components/Admin/Questions.svelte +++ b/frontend/src/lib/components/Admin/Questions.svelte @@ -28,7 +28,7 @@ import DeleteModal from "$lib/components/Admin/DeleteModal.svelte"; import EditButton from "$lib/components/Admin/EditButton.svelte"; import EditQuestionModal from "$lib/components/Admin/EditQuestionModal.svelte"; import { childQuestions, userQuestions } from "$lib/stores/adminStore"; -import { type Component, onMount } from "svelte"; +import { onMount } from "svelte"; import { _, locale } from "svelte-i18n"; import type { Writable } from "svelte/store"; @@ -43,7 +43,6 @@ let create: any; let doDelete: any; let refresh: any; let build: any; -let component: Component = EditQuestionModal; let questions: | Writable> | Writable> @@ -155,8 +154,7 @@ onMount(async () => { {#key showEditQuestionModal} - { const childrenData = await Promise.all( children.data.map(async (child) => { let image = null; - if (child.has_image) { - const childImageResponse = await getChildImage({ - path: { child_id: child.id }, + const childImageResponse = await getChildImage({ + path: { child_id: child.id }, + }); + console.log("childImageResponse", childImageResponse); + if (childImageResponse.error) { + console.log("Error when retrieving child image"); + showAlert = true; + alertMessage = + $_("childData.alertMessageImage") + + " " + + childImageResponse.error.detail; + } else { + const reader = new FileReader(); + reader.readAsDataURL(childImageResponse.data); + image = await new Promise((resolve) => { + reader.onloadend = () => resolve(reader.result as string); }); - if (childImageResponse.error) { - console.log("Error when retrieving child image"); - showAlert = true; - alertMessage = - $_("childData.alertMessageImage") + - childImageResponse.error.detail; - } else { - const reader = new FileReader(); - reader.readAsDataURL(childImageResponse.data); - image = await new Promise((resolve) => { - reader.onloadend = () => resolve(reader.result as string); - }); - } } return { header: child.name, @@ -56,6 +56,7 @@ async function setup(): Promise { // add the 'new child' card as the first element data = [ + ...childrenData, { header: $_("childData.newChildHeading"), summary: $_("childData.newChildHeadingLong"), @@ -67,7 +68,6 @@ async function setup(): Promise { }, image: null, }, - ...childrenData, ]; } return data; @@ -129,6 +129,16 @@ const searchData = [ {#await promise}

{"Waiting for server response"}

{:then data} + {#if showAlert} + { + showAlert = false; + }} + /> + {/if} +
{ } async function submitData(): Promise { - // handle image data - await submitImageData(); - // submit child data await submitChildData(); + // handle image data + await submitImageData(); + // disable all elements to make editing a conscious choice amd go back to childrenGallery console.log("submission of child data successful."); activeTabChildren.set("childrenGallery"); diff --git a/frontend/src/routes/admin/+page.svelte b/frontend/src/routes/admin/+page.svelte new file mode 100644 index 00000000..9e5443a4 --- /dev/null +++ b/frontend/src/routes/admin/+page.svelte @@ -0,0 +1,7 @@ + + + + + diff --git a/mondey_backend/data/dummy.jpg b/mondey_backend/data/dummy.jpg new file mode 100644 index 00000000..589e0f04 Binary files /dev/null and b/mondey_backend/data/dummy.jpg differ diff --git a/mondey_backend/openapi.json b/mondey_backend/openapi.json index fa69d30b..b118eda3 100644 --- a/mondey_backend/openapi.json +++ b/mondey_backend/openapi.json @@ -1 +1 @@ -{"openapi": "3.1.0", "info": {"title": "MONDEY API", "version": "0.1.0"}, "paths": {"/languages/": {"get": {"tags": ["milestones"], "summary": "Get Languages", "operationId": "get_languages", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"type": "string"}, "type": "array", "title": "Response Get Languages Languages Get"}}}}}}}, "/milestones/": {"get": {"tags": ["milestones"], "summary": "Get Milestones", "operationId": "get_milestones", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/MilestonePublic"}, "type": "array", "title": "Response Get Milestones Milestones Get"}}}}}}}, "/milestones/{milestone_id}": {"get": {"tags": ["milestones"], "summary": "Get Milestone", "operationId": "get_milestone", "parameters": [{"name": "milestone_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Milestone Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestonePublic"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/milestone-groups/{child_id}": {"get": {"tags": ["milestones"], "summary": "Get Milestone Groups", "operationId": "get_milestone_groups", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/MilestoneGroupPublic"}, "title": "Response Get Milestone Groups Milestone Groups Child Id Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/user-questions/": {"get": {"tags": ["questions"], "summary": "Get User Questions", "operationId": "get_user_questions", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/UserQuestionPublic"}, "type": "array", "title": "Response Get User Questions User Questions Get"}}}}}}}, "/child-questions/": {"get": {"tags": ["questions"], "summary": "Get Child Questions", "operationId": "get_child_questions", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/ChildQuestionPublic"}, "type": "array", "title": "Response Get Child Questions Child Questions Get"}}}}}}}, "/admin/languages/": {"post": {"tags": ["admin"], "summary": "Create Language", "operationId": "create_language", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Language"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Language"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/admin/languages/{language_id}": {"delete": {"tags": ["admin"], "summary": "Delete Language", "operationId": "delete_language", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "language_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Language Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/i18n/{language_id}": {"put": {"tags": ["admin"], "summary": "Update I18N", "operationId": "update_i18n", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "language_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Language Id"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": {"type": "object", "additionalProperties": {"type": "string"}}, "title": "I18Dict"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/milestone-groups/": {"get": {"tags": ["admin"], "summary": "Get Milestone Groups Admin", "operationId": "get_milestone_groups_admin", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/MilestoneGroupAdmin"}, "type": "array", "title": "Response Get Milestone Groups Admin Admin Milestone Groups Get"}}}}}, "security": [{"APIKeyCookie": []}]}, "post": {"tags": ["admin"], "summary": "Create Milestone Group Admin", "operationId": "create_milestone_group_admin", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneGroupAdmin"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/admin/milestone-groups": {"put": {"tags": ["admin"], "summary": "Update Milestone Group Admin", "operationId": "update_milestone_group_admin", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneGroupAdmin"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneGroupAdmin"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/admin/milestone-groups/{milestone_group_id}": {"delete": {"tags": ["admin"], "summary": "Delete Milestone Group Admin", "operationId": "delete_milestone_group_admin", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "milestone_group_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Milestone Group Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/milestone-group-images/{milestone_group_id}": {"put": {"tags": ["admin"], "summary": "Upload Milestone Group Image", "operationId": "upload_milestone_group_image", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "milestone_group_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Milestone Group Id"}}], "requestBody": {"required": true, "content": {"multipart/form-data": {"schema": {"$ref": "#/components/schemas/Body_upload_milestone_group_image_admin_milestone_group_images__milestone_group_id__put"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/milestones/{milestone_group_id}": {"post": {"tags": ["admin"], "summary": "Create Milestone", "operationId": "create_milestone", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "milestone_group_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Milestone Group Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneAdmin"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/milestones/": {"put": {"tags": ["admin"], "summary": "Update Milestone", "operationId": "update_milestone", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneAdmin"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneAdmin"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/admin/milestones/{milestone_id}": {"delete": {"tags": ["admin"], "summary": "Delete Milestone", "operationId": "delete_milestone", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "milestone_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Milestone Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/milestone-images/{milestone_id}": {"post": {"tags": ["admin"], "summary": "Upload Milestone Image", "operationId": "upload_milestone_image", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "milestone_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Milestone Id"}}], "requestBody": {"required": true, "content": {"multipart/form-data": {"schema": {"$ref": "#/components/schemas/Body_upload_milestone_image_admin_milestone_images__milestone_id__post"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneImage"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/user-questions/": {"get": {"tags": ["admin"], "summary": "Get User Questions Admin", "operationId": "get_user_questions_admin", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/UserQuestionAdmin"}, "type": "array", "title": "Response Get User Questions Admin Admin User Questions Get"}}}}}, "security": [{"APIKeyCookie": []}]}, "put": {"tags": ["admin"], "summary": "Update User Question", "operationId": "update_user_question", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserQuestionAdmin"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserQuestionAdmin"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}, "post": {"tags": ["admin"], "summary": "Create User Question", "operationId": "create_user_question", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserQuestionAdmin"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/admin/user-questions/{user_question_id}": {"delete": {"tags": ["admin"], "summary": "Delete User Question", "operationId": "delete_user_question", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "user_question_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "User Question Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/child-questions/": {"get": {"tags": ["admin"], "summary": "Get Child Questions Admin", "operationId": "get_child_questions_admin", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/ChildQuestionAdmin"}, "type": "array", "title": "Response Get Child Questions Admin Admin Child Questions Get"}}}}}, "security": [{"APIKeyCookie": []}]}, "put": {"tags": ["admin"], "summary": "Update Child Question", "operationId": "update_child_question", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildQuestionAdmin"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildQuestionAdmin"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}, "post": {"tags": ["admin"], "summary": "Create Child Question", "operationId": "create_child_question", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildQuestionAdmin"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/admin/child-questions/{child_question_id}": {"delete": {"tags": ["admin"], "summary": "Delete Child Question", "operationId": "delete_child_question", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_question_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Question Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/users/me": {"get": {"tags": ["users"], "summary": "Users:Current User", "operationId": "users:current_user", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserRead"}}}}, "401": {"description": "Missing token or inactive user."}}, "security": [{"APIKeyCookie": []}]}, "patch": {"tags": ["users"], "summary": "Users:Patch Current User", "operationId": "users:patch_current_user", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserUpdate"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserRead"}}}}, "401": {"description": "Missing token or inactive user."}, "400": {"description": "Bad Request", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorModel"}, "examples": {"UPDATE_USER_EMAIL_ALREADY_EXISTS": {"summary": "A user with this email already exists.", "value": {"detail": "UPDATE_USER_EMAIL_ALREADY_EXISTS"}}, "UPDATE_USER_INVALID_PASSWORD": {"summary": "Password validation failed.", "value": {"detail": {"code": "UPDATE_USER_INVALID_PASSWORD", "reason": "Password should beat least 3 characters"}}}}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/users/{id}": {"get": {"tags": ["users"], "summary": "Users:User", "operationId": "users:user", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string", "title": "Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserRead"}}}}, "401": {"description": "Missing token or inactive user."}, "403": {"description": "Not a superuser."}, "404": {"description": "The user does not exist."}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["users"], "summary": "Users:Patch User", "operationId": "users:patch_user", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string", "title": "Id"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserRead"}}}}, "401": {"description": "Missing token or inactive user."}, "403": {"description": "Not a superuser."}, "404": {"description": "The user does not exist."}, "400": {"content": {"application/json": {"examples": {"UPDATE_USER_EMAIL_ALREADY_EXISTS": {"summary": "A user with this email already exists.", "value": {"detail": "UPDATE_USER_EMAIL_ALREADY_EXISTS"}}, "UPDATE_USER_INVALID_PASSWORD": {"summary": "Password validation failed.", "value": {"detail": {"code": "UPDATE_USER_INVALID_PASSWORD", "reason": "Password should beat least 3 characters"}}}}, "schema": {"$ref": "#/components/schemas/ErrorModel"}}}, "description": "Bad Request"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["users"], "summary": "Users:Delete User", "operationId": "users:delete_user", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string", "title": "Id"}}], "responses": {"204": {"description": "Successful Response"}, "401": {"description": "Missing token or inactive user."}, "403": {"description": "Not a superuser."}, "404": {"description": "The user does not exist."}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/users/children/": {"get": {"tags": ["users"], "summary": "Get Children", "operationId": "get_children", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/ChildPublic"}, "type": "array", "title": "Response Get Children Users Children Get"}}}}}, "security": [{"APIKeyCookie": []}]}, "put": {"tags": ["users"], "summary": "Update Child", "operationId": "update_child", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildPublic"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildPublic"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}, "post": {"tags": ["users"], "summary": "Create Child", "operationId": "create_child", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildCreate"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildPublic"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/users/children/{child_id}": {"get": {"tags": ["users"], "summary": "Get Child", "operationId": "get_child", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildPublic"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["users"], "summary": "Delete Child", "operationId": "delete_child", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/users/children-images/{child_id}": {"get": {"tags": ["users"], "summary": "Get Child Image", "operationId": "get_child_image", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "responses": {"200": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "put": {"tags": ["users"], "summary": "Upload Child Image", "operationId": "upload_child_image", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "requestBody": {"required": true, "content": {"multipart/form-data": {"schema": {"$ref": "#/components/schemas/Body_upload_child_image_users_children_images__child_id__put"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["users"], "summary": "Delete Child Image", "operationId": "delete_child_image", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/users/milestone-answers/{child_id}": {"get": {"tags": ["users"], "summary": "Get Current Milestone Answer Session", "operationId": "get_current_milestone_answer_session", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneAnswerSessionPublic"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/users/milestone-answers/{milestone_answer_session_id}": {"put": {"tags": ["users"], "summary": "Update Milestone Answer", "operationId": "update_milestone_answer", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "milestone_answer_session_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Milestone Answer Session Id"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneAnswerPublic"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneAnswerPublic"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/users/user-answers/": {"get": {"tags": ["users"], "summary": "Get Current User Answers", "operationId": "get_current_user_answers", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/UserAnswerPublic"}, "type": "array", "title": "Response Get Current User Answers Users User Answers Get"}}}}}, "security": [{"APIKeyCookie": []}]}, "put": {"tags": ["users"], "summary": "Update Current User Answers", "operationId": "update_current_user_answers", "requestBody": {"content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/UserAnswerPublic"}, "type": "array", "title": "New Answers"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/UserAnswerPublic"}, "type": "array", "title": "Response Update Current User Answers Users User Answers Put"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/users/children-answers/{child_id}": {"get": {"tags": ["users"], "summary": "Get Current Child Answers", "operationId": "get_current_child_answers", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "object", "additionalProperties": {"$ref": "#/components/schemas/ChildAnswerPublic"}, "title": "Response Get Current Child Answers Users Children Answers Child Id Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "put": {"tags": ["users"], "summary": "Update Current Child Answers", "operationId": "update_current_child_answers", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": {"$ref": "#/components/schemas/ChildAnswerPublic"}, "title": "New Answers"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/auth/login": {"post": {"tags": ["auth"], "summary": "Auth:Cookie.Login", "operationId": "auth:cookie.login", "requestBody": {"content": {"application/x-www-form-urlencoded": {"schema": {"$ref": "#/components/schemas/Body_auth_cookie_login_auth_login_post"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "400": {"description": "Bad Request", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorModel"}, "examples": {"LOGIN_BAD_CREDENTIALS": {"summary": "Bad credentials or the user is inactive.", "value": {"detail": "LOGIN_BAD_CREDENTIALS"}}, "LOGIN_USER_NOT_VERIFIED": {"summary": "The user is not verified.", "value": {"detail": "LOGIN_USER_NOT_VERIFIED"}}}}}}, "204": {"description": "No Content"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/auth/logout": {"post": {"tags": ["auth"], "summary": "Auth:Cookie.Logout", "operationId": "auth:cookie.logout", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "401": {"description": "Missing token or inactive user."}, "204": {"description": "No Content"}}, "security": [{"APIKeyCookie": []}]}}, "/auth/register": {"post": {"tags": ["auth"], "summary": "Register:Register", "operationId": "register:register", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserCreate"}}}, "required": true}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserRead"}}}}, "400": {"description": "Bad Request", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorModel"}, "examples": {"REGISTER_USER_ALREADY_EXISTS": {"summary": "A user with this email already exists.", "value": {"detail": "REGISTER_USER_ALREADY_EXISTS"}}, "REGISTER_INVALID_PASSWORD": {"summary": "Password validation failed.", "value": {"detail": {"code": "REGISTER_INVALID_PASSWORD", "reason": "Password should beat least 3 characters"}}}}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/auth/forgot-password": {"post": {"tags": ["auth"], "summary": "Reset:Forgot Password", "operationId": "reset:forgot_password", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Body_reset_forgot_password_auth_forgot_password_post"}}}, "required": true}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/auth/reset-password": {"post": {"tags": ["auth"], "summary": "Reset:Reset Password", "operationId": "reset:reset_password", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Body_reset_reset_password_auth_reset_password_post"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "400": {"description": "Bad Request", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorModel"}, "examples": {"RESET_PASSWORD_BAD_TOKEN": {"summary": "Bad or expired token.", "value": {"detail": "RESET_PASSWORD_BAD_TOKEN"}}, "RESET_PASSWORD_INVALID_PASSWORD": {"summary": "Password validation failed.", "value": {"detail": {"code": "RESET_PASSWORD_INVALID_PASSWORD", "reason": "Password should be at least 3 characters"}}}}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/auth/request-verify-token": {"post": {"tags": ["auth"], "summary": "Verify:Request-Token", "operationId": "verify:request-token", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Body_verify_request_token_auth_request_verify_token_post"}}}, "required": true}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/auth/verify": {"post": {"tags": ["auth"], "summary": "Verify:Verify", "operationId": "verify:verify", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Body_verify_verify_auth_verify_post"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserRead"}}}}, "400": {"description": "Bad Request", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorModel"}, "examples": {"VERIFY_USER_BAD_TOKEN": {"summary": "Bad token, not existing user ornot the e-mail currently set for the user.", "value": {"detail": "VERIFY_USER_BAD_TOKEN"}}, "VERIFY_USER_ALREADY_VERIFIED": {"summary": "The user is already verified.", "value": {"detail": "VERIFY_USER_ALREADY_VERIFIED"}}}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/research/auth/": {"get": {"tags": ["research"], "summary": "Auth", "operationId": "auth", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}}, "security": [{"APIKeyCookie": []}]}}}, "components": {"schemas": {"Body_auth_cookie_login_auth_login_post": {"properties": {"grant_type": {"anyOf": [{"type": "string", "pattern": "password"}, {"type": "null"}], "title": "Grant Type"}, "username": {"type": "string", "title": "Username"}, "password": {"type": "string", "title": "Password"}, "scope": {"type": "string", "title": "Scope", "default": ""}, "client_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Client Id"}, "client_secret": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Client Secret"}}, "type": "object", "required": ["username", "password"], "title": "Body_auth_cookie_login_auth_login_post"}, "Body_reset_forgot_password_auth_forgot_password_post": {"properties": {"email": {"type": "string", "format": "email", "title": "Email"}}, "type": "object", "required": ["email"], "title": "Body_reset_forgot_password_auth_forgot_password_post"}, "Body_reset_reset_password_auth_reset_password_post": {"properties": {"token": {"type": "string", "title": "Token"}, "password": {"type": "string", "title": "Password"}}, "type": "object", "required": ["token", "password"], "title": "Body_reset_reset_password_auth_reset_password_post"}, "Body_upload_child_image_users_children_images__child_id__put": {"properties": {"file": {"type": "string", "format": "binary", "title": "File"}}, "type": "object", "required": ["file"], "title": "Body_upload_child_image_users_children_images__child_id__put"}, "Body_upload_milestone_group_image_admin_milestone_group_images__milestone_group_id__put": {"properties": {"file": {"type": "string", "format": "binary", "title": "File"}}, "type": "object", "required": ["file"], "title": "Body_upload_milestone_group_image_admin_milestone_group_images__milestone_group_id__put"}, "Body_upload_milestone_image_admin_milestone_images__milestone_id__post": {"properties": {"file": {"type": "string", "format": "binary", "title": "File"}}, "type": "object", "required": ["file"], "title": "Body_upload_milestone_image_admin_milestone_images__milestone_id__post"}, "Body_verify_request_token_auth_request_verify_token_post": {"properties": {"email": {"type": "string", "format": "email", "title": "Email"}}, "type": "object", "required": ["email"], "title": "Body_verify_request_token_auth_request_verify_token_post"}, "Body_verify_verify_auth_verify_post": {"properties": {"token": {"type": "string", "title": "Token"}}, "type": "object", "required": ["token"], "title": "Body_verify_verify_auth_verify_post"}, "ChildAnswerPublic": {"properties": {"answer": {"type": "string", "title": "Answer"}, "additional_answer": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Additional Answer"}, "question_id": {"type": "integer", "title": "Question Id"}}, "type": "object", "required": ["answer", "additional_answer", "question_id"], "title": "ChildAnswerPublic"}, "ChildCreate": {"properties": {"name": {"type": "string", "title": "Name", "default": ""}, "birth_year": {"type": "integer", "title": "Birth Year"}, "birth_month": {"type": "integer", "title": "Birth Month"}}, "type": "object", "required": ["birth_year", "birth_month"], "title": "ChildCreate"}, "ChildPublic": {"properties": {"name": {"type": "string", "title": "Name", "default": ""}, "birth_year": {"type": "integer", "title": "Birth Year"}, "birth_month": {"type": "integer", "title": "Birth Month"}, "id": {"type": "integer", "title": "Id"}, "has_image": {"type": "boolean", "title": "Has Image"}}, "type": "object", "required": ["birth_year", "birth_month", "id", "has_image"], "title": "ChildPublic"}, "ChildQuestionAdmin": {"properties": {"order": {"type": "integer", "title": "Order", "default": 0}, "component": {"type": "string", "title": "Component", "default": "select"}, "type": {"type": "string", "title": "Type", "default": "text"}, "options": {"type": "string", "title": "Options", "default": ""}, "additional_option": {"type": "string", "title": "Additional Option", "default": ""}, "id": {"type": "integer", "title": "Id"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/ChildQuestionText"}, "type": "object", "title": "Text", "default": {}}}, "type": "object", "required": ["id"], "title": "ChildQuestionAdmin"}, "ChildQuestionPublic": {"properties": {"id": {"type": "integer", "title": "Id"}, "component": {"type": "string", "title": "Component", "default": "select"}, "type": {"type": "string", "title": "Type", "default": "text"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/QuestionTextPublic"}, "type": "object", "title": "Text", "default": {}}, "additional_option": {"type": "string", "title": "Additional Option", "default": ""}}, "type": "object", "required": ["id"], "title": "ChildQuestionPublic"}, "ChildQuestionText": {"properties": {"question": {"type": "string", "title": "Question", "default": ""}, "options_json": {"type": "string", "title": "Options Json", "default": ""}, "options": {"type": "string", "title": "Options", "default": ""}, "child_question_id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Child Question Id"}, "lang_id": {"anyOf": [{"type": "string", "maxLength": 2}, {"type": "null"}], "title": "Lang Id"}}, "type": "object", "title": "ChildQuestionText"}, "ErrorModel": {"properties": {"detail": {"anyOf": [{"type": "string"}, {"additionalProperties": {"type": "string"}, "type": "object"}], "title": "Detail"}}, "type": "object", "required": ["detail"], "title": "ErrorModel"}, "HTTPValidationError": {"properties": {"detail": {"items": {"$ref": "#/components/schemas/ValidationError"}, "type": "array", "title": "Detail"}}, "type": "object", "title": "HTTPValidationError"}, "Language": {"properties": {"id": {"type": "string", "maxLength": 2, "title": "Id"}}, "type": "object", "required": ["id"], "title": "Language"}, "MilestoneAdmin": {"properties": {"id": {"type": "integer", "title": "Id"}, "group_id": {"type": "integer", "title": "Group Id"}, "order": {"type": "integer", "title": "Order"}, "expected_age_months": {"type": "integer", "title": "Expected Age Months"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/MilestoneText"}, "type": "object", "title": "Text", "default": {}}, "images": {"items": {"$ref": "#/components/schemas/MilestoneImage"}, "type": "array", "title": "Images", "default": []}}, "type": "object", "required": ["id", "group_id", "order", "expected_age_months"], "title": "MilestoneAdmin"}, "MilestoneAnswerPublic": {"properties": {"milestone_id": {"type": "integer", "title": "Milestone Id"}, "answer": {"type": "integer", "title": "Answer"}}, "type": "object", "required": ["milestone_id", "answer"], "title": "MilestoneAnswerPublic"}, "MilestoneAnswerSessionPublic": {"properties": {"id": {"type": "integer", "title": "Id"}, "child_id": {"type": "integer", "title": "Child Id"}, "created_at": {"type": "string", "format": "date-time", "title": "Created At"}, "answers": {"additionalProperties": {"$ref": "#/components/schemas/MilestoneAnswerPublic"}, "type": "object", "title": "Answers"}}, "type": "object", "required": ["id", "child_id", "created_at", "answers"], "title": "MilestoneAnswerSessionPublic"}, "MilestoneGroupAdmin": {"properties": {"id": {"type": "integer", "title": "Id"}, "order": {"type": "integer", "title": "Order"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/MilestoneGroupText"}, "type": "object", "title": "Text", "default": {}}, "milestones": {"items": {"$ref": "#/components/schemas/MilestoneAdmin"}, "type": "array", "title": "Milestones", "default": []}}, "type": "object", "required": ["id", "order"], "title": "MilestoneGroupAdmin"}, "MilestoneGroupPublic": {"properties": {"id": {"type": "integer", "title": "Id"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/MilestoneGroupTextPublic"}, "type": "object", "title": "Text", "default": {}}, "milestones": {"items": {"$ref": "#/components/schemas/MilestonePublic"}, "type": "array", "title": "Milestones", "default": []}}, "type": "object", "required": ["id"], "title": "MilestoneGroupPublic"}, "MilestoneGroupText": {"properties": {"title": {"type": "string", "title": "Title", "default": ""}, "desc": {"type": "string", "title": "Desc", "default": ""}, "group_id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Group Id"}, "lang_id": {"anyOf": [{"type": "string", "maxLength": 2}, {"type": "null"}], "title": "Lang Id"}}, "type": "object", "title": "MilestoneGroupText"}, "MilestoneGroupTextPublic": {"properties": {"title": {"type": "string", "title": "Title", "default": ""}, "desc": {"type": "string", "title": "Desc", "default": ""}}, "type": "object", "title": "MilestoneGroupTextPublic"}, "MilestoneImage": {"properties": {"id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Id"}, "milestone_id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Milestone Id"}, "filename": {"type": "string", "title": "Filename", "default": ""}, "approved": {"type": "boolean", "title": "Approved", "default": false}}, "type": "object", "title": "MilestoneImage"}, "MilestoneImagePublic": {"properties": {"filename": {"type": "string", "title": "Filename"}, "approved": {"type": "boolean", "title": "Approved"}}, "type": "object", "required": ["filename", "approved"], "title": "MilestoneImagePublic"}, "MilestonePublic": {"properties": {"id": {"type": "integer", "title": "Id"}, "expected_age_months": {"type": "integer", "title": "Expected Age Months"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/MilestoneTextPublic"}, "type": "object", "title": "Text", "default": {}}, "images": {"items": {"$ref": "#/components/schemas/MilestoneImagePublic"}, "type": "array", "title": "Images", "default": []}}, "type": "object", "required": ["id", "expected_age_months"], "title": "MilestonePublic"}, "MilestoneText": {"properties": {"title": {"type": "string", "title": "Title", "default": ""}, "desc": {"type": "string", "title": "Desc", "default": ""}, "obs": {"type": "string", "title": "Obs", "default": ""}, "help": {"type": "string", "title": "Help", "default": ""}, "milestone_id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Milestone Id"}, "lang_id": {"anyOf": [{"type": "string", "maxLength": 2}, {"type": "null"}], "title": "Lang Id"}}, "type": "object", "title": "MilestoneText"}, "MilestoneTextPublic": {"properties": {"title": {"type": "string", "title": "Title", "default": ""}, "desc": {"type": "string", "title": "Desc", "default": ""}, "obs": {"type": "string", "title": "Obs", "default": ""}, "help": {"type": "string", "title": "Help", "default": ""}}, "type": "object", "title": "MilestoneTextPublic"}, "QuestionTextPublic": {"properties": {"question": {"type": "string", "title": "Question", "default": ""}, "options_json": {"type": "string", "title": "Options Json", "default": ""}, "options": {"type": "string", "title": "Options", "default": ""}}, "type": "object", "title": "QuestionTextPublic"}, "UserAnswerPublic": {"properties": {"answer": {"type": "string", "title": "Answer"}, "additional_answer": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Additional Answer"}, "question_id": {"type": "integer", "title": "Question Id"}}, "type": "object", "required": ["answer", "additional_answer", "question_id"], "title": "UserAnswerPublic"}, "UserCreate": {"properties": {"email": {"type": "string", "format": "email", "title": "Email"}, "password": {"type": "string", "title": "Password"}, "is_active": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Active", "default": true}, "is_superuser": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Superuser", "default": false}, "is_verified": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Verified", "default": false}, "is_researcher": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Researcher", "default": false}}, "type": "object", "required": ["email", "password"], "title": "UserCreate"}, "UserQuestionAdmin": {"properties": {"order": {"type": "integer", "title": "Order", "default": 0}, "component": {"type": "string", "title": "Component", "default": "select"}, "type": {"type": "string", "title": "Type", "default": "text"}, "options": {"type": "string", "title": "Options", "default": ""}, "additional_option": {"type": "string", "title": "Additional Option", "default": ""}, "id": {"type": "integer", "title": "Id"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/UserQuestionText"}, "type": "object", "title": "Text", "default": {}}}, "type": "object", "required": ["id"], "title": "UserQuestionAdmin"}, "UserQuestionPublic": {"properties": {"id": {"type": "integer", "title": "Id"}, "component": {"type": "string", "title": "Component", "default": "select"}, "type": {"type": "string", "title": "Type", "default": "text"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/QuestionTextPublic"}, "type": "object", "title": "Text", "default": {}}, "additional_option": {"type": "string", "title": "Additional Option", "default": ""}}, "type": "object", "required": ["id"], "title": "UserQuestionPublic"}, "UserQuestionText": {"properties": {"question": {"type": "string", "title": "Question", "default": ""}, "options_json": {"type": "string", "title": "Options Json", "default": ""}, "options": {"type": "string", "title": "Options", "default": ""}, "user_question_id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "User Question Id"}, "lang_id": {"anyOf": [{"type": "string", "maxLength": 2}, {"type": "null"}], "title": "Lang Id"}}, "type": "object", "title": "UserQuestionText"}, "UserRead": {"properties": {"id": {"type": "integer", "title": "Id"}, "email": {"type": "string", "format": "email", "title": "Email"}, "is_active": {"type": "boolean", "title": "Is Active", "default": true}, "is_superuser": {"type": "boolean", "title": "Is Superuser", "default": false}, "is_verified": {"type": "boolean", "title": "Is Verified", "default": false}, "is_researcher": {"type": "boolean", "title": "Is Researcher"}}, "type": "object", "required": ["id", "email", "is_researcher"], "title": "UserRead"}, "UserUpdate": {"properties": {"password": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Password"}, "email": {"anyOf": [{"type": "string", "format": "email"}, {"type": "null"}], "title": "Email"}, "is_active": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Active"}, "is_superuser": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Superuser"}, "is_verified": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Verified"}, "is_researcher": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Researcher"}}, "type": "object", "title": "UserUpdate"}, "ValidationError": {"properties": {"loc": {"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, "type": "array", "title": "Location"}, "msg": {"type": "string", "title": "Message"}, "type": {"type": "string", "title": "Error Type"}}, "type": "object", "required": ["loc", "msg", "type"], "title": "ValidationError"}}, "securitySchemes": {"APIKeyCookie": {"type": "apiKey", "in": "cookie", "name": "fastapiusersauth"}}}} \ No newline at end of file +{"openapi": "3.1.0", "info": {"title": "MONDEY API", "version": "0.1.0"}, "paths": {"/languages/": {"get": {"tags": ["milestones"], "summary": "Get Languages", "operationId": "get_languages", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"type": "string"}, "type": "array", "title": "Response Get Languages Languages Get"}}}}}}}, "/milestones/": {"get": {"tags": ["milestones"], "summary": "Get Milestones", "operationId": "get_milestones", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/MilestonePublic"}, "type": "array", "title": "Response Get Milestones Milestones Get"}}}}}}}, "/milestones/{milestone_id}": {"get": {"tags": ["milestones"], "summary": "Get Milestone", "operationId": "get_milestone", "parameters": [{"name": "milestone_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Milestone Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestonePublic"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/milestone-groups/{child_id}": {"get": {"tags": ["milestones"], "summary": "Get Milestone Groups", "operationId": "get_milestone_groups", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/MilestoneGroupPublic"}, "title": "Response Get Milestone Groups Milestone Groups Child Id Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/user-questions/": {"get": {"tags": ["questions"], "summary": "Get User Questions", "operationId": "get_user_questions", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/UserQuestionPublic"}, "type": "array", "title": "Response Get User Questions User Questions Get"}}}}}}}, "/child-questions/": {"get": {"tags": ["questions"], "summary": "Get Child Questions", "operationId": "get_child_questions", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/ChildQuestionPublic"}, "type": "array", "title": "Response Get Child Questions Child Questions Get"}}}}}}}, "/admin/languages/": {"post": {"tags": ["admin"], "summary": "Create Language", "operationId": "create_language", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Language"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Language"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/admin/languages/{language_id}": {"delete": {"tags": ["admin"], "summary": "Delete Language", "operationId": "delete_language", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "language_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Language Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/i18n/{language_id}": {"put": {"tags": ["admin"], "summary": "Update I18N", "operationId": "update_i18n", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "language_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Language Id"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": {"type": "object", "additionalProperties": {"type": "string"}}, "title": "I18Dict"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/milestone-groups/": {"get": {"tags": ["admin"], "summary": "Get Milestone Groups Admin", "operationId": "get_milestone_groups_admin", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/MilestoneGroupAdmin"}, "type": "array", "title": "Response Get Milestone Groups Admin Admin Milestone Groups Get"}}}}}, "security": [{"APIKeyCookie": []}]}, "post": {"tags": ["admin"], "summary": "Create Milestone Group Admin", "operationId": "create_milestone_group_admin", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneGroupAdmin"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/admin/milestone-groups": {"put": {"tags": ["admin"], "summary": "Update Milestone Group Admin", "operationId": "update_milestone_group_admin", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneGroupAdmin"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneGroupAdmin"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/admin/milestone-groups/{milestone_group_id}": {"delete": {"tags": ["admin"], "summary": "Delete Milestone Group Admin", "operationId": "delete_milestone_group_admin", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "milestone_group_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Milestone Group Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/milestone-group-images/{milestone_group_id}": {"put": {"tags": ["admin"], "summary": "Upload Milestone Group Image", "operationId": "upload_milestone_group_image", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "milestone_group_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Milestone Group Id"}}], "requestBody": {"required": true, "content": {"multipart/form-data": {"schema": {"$ref": "#/components/schemas/Body_upload_milestone_group_image_admin_milestone_group_images__milestone_group_id__put"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/milestones/{milestone_group_id}": {"post": {"tags": ["admin"], "summary": "Create Milestone", "operationId": "create_milestone", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "milestone_group_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Milestone Group Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneAdmin"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/milestones/": {"put": {"tags": ["admin"], "summary": "Update Milestone", "operationId": "update_milestone", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneAdmin"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneAdmin"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/admin/milestones/{milestone_id}": {"delete": {"tags": ["admin"], "summary": "Delete Milestone", "operationId": "delete_milestone", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "milestone_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Milestone Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/milestone-images/{milestone_id}": {"post": {"tags": ["admin"], "summary": "Upload Milestone Image", "operationId": "upload_milestone_image", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "milestone_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Milestone Id"}}], "requestBody": {"required": true, "content": {"multipart/form-data": {"schema": {"$ref": "#/components/schemas/Body_upload_milestone_image_admin_milestone_images__milestone_id__post"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneImage"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/milestone-images/{milestone_image_id}": {"delete": {"tags": ["admin"], "summary": "Delete Milestone Image", "operationId": "delete_milestone_image", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "milestone_image_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Milestone Image Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/user-questions/": {"get": {"tags": ["admin"], "summary": "Get User Questions Admin", "operationId": "get_user_questions_admin", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/UserQuestionAdmin"}, "type": "array", "title": "Response Get User Questions Admin Admin User Questions Get"}}}}}, "security": [{"APIKeyCookie": []}]}, "put": {"tags": ["admin"], "summary": "Update User Question", "operationId": "update_user_question", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserQuestionAdmin"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserQuestionAdmin"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}, "post": {"tags": ["admin"], "summary": "Create User Question", "operationId": "create_user_question", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserQuestionAdmin"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/admin/user-questions/{user_question_id}": {"delete": {"tags": ["admin"], "summary": "Delete User Question", "operationId": "delete_user_question", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "user_question_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "User Question Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/admin/child-questions/": {"get": {"tags": ["admin"], "summary": "Get Child Questions Admin", "operationId": "get_child_questions_admin", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/ChildQuestionAdmin"}, "type": "array", "title": "Response Get Child Questions Admin Admin Child Questions Get"}}}}}, "security": [{"APIKeyCookie": []}]}, "put": {"tags": ["admin"], "summary": "Update Child Question", "operationId": "update_child_question", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildQuestionAdmin"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildQuestionAdmin"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}, "post": {"tags": ["admin"], "summary": "Create Child Question", "operationId": "create_child_question", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildQuestionAdmin"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/admin/child-questions/{child_question_id}": {"delete": {"tags": ["admin"], "summary": "Delete Child Question", "operationId": "delete_child_question", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_question_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Question Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/users/me": {"get": {"tags": ["users"], "summary": "Users:Current User", "operationId": "users:current_user", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserRead"}}}}, "401": {"description": "Missing token or inactive user."}}, "security": [{"APIKeyCookie": []}]}, "patch": {"tags": ["users"], "summary": "Users:Patch Current User", "operationId": "users:patch_current_user", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserUpdate"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserRead"}}}}, "401": {"description": "Missing token or inactive user."}, "400": {"description": "Bad Request", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorModel"}, "examples": {"UPDATE_USER_EMAIL_ALREADY_EXISTS": {"summary": "A user with this email already exists.", "value": {"detail": "UPDATE_USER_EMAIL_ALREADY_EXISTS"}}, "UPDATE_USER_INVALID_PASSWORD": {"summary": "Password validation failed.", "value": {"detail": {"code": "UPDATE_USER_INVALID_PASSWORD", "reason": "Password should beat least 3 characters"}}}}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/users/{id}": {"get": {"tags": ["users"], "summary": "Users:User", "operationId": "users:user", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string", "title": "Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserRead"}}}}, "401": {"description": "Missing token or inactive user."}, "403": {"description": "Not a superuser."}, "404": {"description": "The user does not exist."}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["users"], "summary": "Users:Patch User", "operationId": "users:patch_user", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string", "title": "Id"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserRead"}}}}, "401": {"description": "Missing token or inactive user."}, "403": {"description": "Not a superuser."}, "404": {"description": "The user does not exist."}, "400": {"content": {"application/json": {"examples": {"UPDATE_USER_EMAIL_ALREADY_EXISTS": {"summary": "A user with this email already exists.", "value": {"detail": "UPDATE_USER_EMAIL_ALREADY_EXISTS"}}, "UPDATE_USER_INVALID_PASSWORD": {"summary": "Password validation failed.", "value": {"detail": {"code": "UPDATE_USER_INVALID_PASSWORD", "reason": "Password should beat least 3 characters"}}}}, "schema": {"$ref": "#/components/schemas/ErrorModel"}}}, "description": "Bad Request"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["users"], "summary": "Users:Delete User", "operationId": "users:delete_user", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string", "title": "Id"}}], "responses": {"204": {"description": "Successful Response"}, "401": {"description": "Missing token or inactive user."}, "403": {"description": "Not a superuser."}, "404": {"description": "The user does not exist."}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/users/children/": {"get": {"tags": ["users"], "summary": "Get Children", "operationId": "get_children", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/ChildPublic"}, "type": "array", "title": "Response Get Children Users Children Get"}}}}}, "security": [{"APIKeyCookie": []}]}, "put": {"tags": ["users"], "summary": "Update Child", "operationId": "update_child", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildPublic"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildPublic"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}, "post": {"tags": ["users"], "summary": "Create Child", "operationId": "create_child", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildCreate"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildPublic"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/users/children/{child_id}": {"get": {"tags": ["users"], "summary": "Get Child", "operationId": "get_child", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChildPublic"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["users"], "summary": "Delete Child", "operationId": "delete_child", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/users/children-images/{child_id}": {"get": {"tags": ["users"], "summary": "Get Child Image", "operationId": "get_child_image", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "responses": {"200": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "put": {"tags": ["users"], "summary": "Upload Child Image", "operationId": "upload_child_image", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "requestBody": {"required": true, "content": {"multipart/form-data": {"schema": {"$ref": "#/components/schemas/Body_upload_child_image_users_children_images__child_id__put"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["users"], "summary": "Delete Child Image", "operationId": "delete_child_image", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/users/milestone-answers/{child_id}": {"get": {"tags": ["users"], "summary": "Get Current Milestone Answer Session", "operationId": "get_current_milestone_answer_session", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneAnswerSessionPublic"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/users/milestone-answers/{milestone_answer_session_id}": {"put": {"tags": ["users"], "summary": "Update Milestone Answer", "operationId": "update_milestone_answer", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "milestone_answer_session_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Milestone Answer Session Id"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneAnswerPublic"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MilestoneAnswerPublic"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/users/user-answers/": {"get": {"tags": ["users"], "summary": "Get Current User Answers", "operationId": "get_current_user_answers", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/UserAnswerPublic"}, "type": "array", "title": "Response Get Current User Answers Users User Answers Get"}}}}}, "security": [{"APIKeyCookie": []}]}, "put": {"tags": ["users"], "summary": "Update Current User Answers", "operationId": "update_current_user_answers", "requestBody": {"content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/UserAnswerPublic"}, "type": "array", "title": "New Answers"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/UserAnswerPublic"}, "type": "array", "title": "Response Update Current User Answers Users User Answers Put"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}, "security": [{"APIKeyCookie": []}]}}, "/users/children-answers/{child_id}": {"get": {"tags": ["users"], "summary": "Get Current Child Answers", "operationId": "get_current_child_answers", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "object", "additionalProperties": {"$ref": "#/components/schemas/ChildAnswerPublic"}, "title": "Response Get Current Child Answers Users Children Answers Child Id Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "put": {"tags": ["users"], "summary": "Update Current Child Answers", "operationId": "update_current_child_answers", "security": [{"APIKeyCookie": []}], "parameters": [{"name": "child_id", "in": "path", "required": true, "schema": {"type": "integer", "title": "Child Id"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": {"$ref": "#/components/schemas/ChildAnswerPublic"}, "title": "New Answers"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/auth/login": {"post": {"tags": ["auth"], "summary": "Auth:Cookie.Login", "operationId": "auth:cookie.login", "requestBody": {"content": {"application/x-www-form-urlencoded": {"schema": {"$ref": "#/components/schemas/Body_auth_cookie_login_auth_login_post"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "400": {"description": "Bad Request", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorModel"}, "examples": {"LOGIN_BAD_CREDENTIALS": {"summary": "Bad credentials or the user is inactive.", "value": {"detail": "LOGIN_BAD_CREDENTIALS"}}, "LOGIN_USER_NOT_VERIFIED": {"summary": "The user is not verified.", "value": {"detail": "LOGIN_USER_NOT_VERIFIED"}}}}}}, "204": {"description": "No Content"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/auth/logout": {"post": {"tags": ["auth"], "summary": "Auth:Cookie.Logout", "operationId": "auth:cookie.logout", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "401": {"description": "Missing token or inactive user."}, "204": {"description": "No Content"}}, "security": [{"APIKeyCookie": []}]}}, "/auth/register": {"post": {"tags": ["auth"], "summary": "Register:Register", "operationId": "register:register", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserCreate"}}}, "required": true}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserRead"}}}}, "400": {"description": "Bad Request", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorModel"}, "examples": {"REGISTER_USER_ALREADY_EXISTS": {"summary": "A user with this email already exists.", "value": {"detail": "REGISTER_USER_ALREADY_EXISTS"}}, "REGISTER_INVALID_PASSWORD": {"summary": "Password validation failed.", "value": {"detail": {"code": "REGISTER_INVALID_PASSWORD", "reason": "Password should beat least 3 characters"}}}}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/auth/forgot-password": {"post": {"tags": ["auth"], "summary": "Reset:Forgot Password", "operationId": "reset:forgot_password", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Body_reset_forgot_password_auth_forgot_password_post"}}}, "required": true}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/auth/reset-password": {"post": {"tags": ["auth"], "summary": "Reset:Reset Password", "operationId": "reset:reset_password", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Body_reset_reset_password_auth_reset_password_post"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "400": {"description": "Bad Request", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorModel"}, "examples": {"RESET_PASSWORD_BAD_TOKEN": {"summary": "Bad or expired token.", "value": {"detail": "RESET_PASSWORD_BAD_TOKEN"}}, "RESET_PASSWORD_INVALID_PASSWORD": {"summary": "Password validation failed.", "value": {"detail": {"code": "RESET_PASSWORD_INVALID_PASSWORD", "reason": "Password should be at least 3 characters"}}}}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/auth/request-verify-token": {"post": {"tags": ["auth"], "summary": "Verify:Request-Token", "operationId": "verify:request-token", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Body_verify_request_token_auth_request_verify_token_post"}}}, "required": true}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/auth/verify": {"post": {"tags": ["auth"], "summary": "Verify:Verify", "operationId": "verify:verify", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Body_verify_verify_auth_verify_post"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserRead"}}}}, "400": {"description": "Bad Request", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorModel"}, "examples": {"VERIFY_USER_BAD_TOKEN": {"summary": "Bad token, not existing user ornot the e-mail currently set for the user.", "value": {"detail": "VERIFY_USER_BAD_TOKEN"}}, "VERIFY_USER_ALREADY_VERIFIED": {"summary": "The user is already verified.", "value": {"detail": "VERIFY_USER_ALREADY_VERIFIED"}}}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/research/auth/": {"get": {"tags": ["research"], "summary": "Auth", "operationId": "auth", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}}, "security": [{"APIKeyCookie": []}]}}}, "components": {"schemas": {"Body_auth_cookie_login_auth_login_post": {"properties": {"grant_type": {"anyOf": [{"type": "string", "pattern": "password"}, {"type": "null"}], "title": "Grant Type"}, "username": {"type": "string", "title": "Username"}, "password": {"type": "string", "title": "Password"}, "scope": {"type": "string", "title": "Scope", "default": ""}, "client_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Client Id"}, "client_secret": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Client Secret"}}, "type": "object", "required": ["username", "password"], "title": "Body_auth_cookie_login_auth_login_post"}, "Body_reset_forgot_password_auth_forgot_password_post": {"properties": {"email": {"type": "string", "format": "email", "title": "Email"}}, "type": "object", "required": ["email"], "title": "Body_reset_forgot_password_auth_forgot_password_post"}, "Body_reset_reset_password_auth_reset_password_post": {"properties": {"token": {"type": "string", "title": "Token"}, "password": {"type": "string", "title": "Password"}}, "type": "object", "required": ["token", "password"], "title": "Body_reset_reset_password_auth_reset_password_post"}, "Body_upload_child_image_users_children_images__child_id__put": {"properties": {"file": {"type": "string", "format": "binary", "title": "File"}}, "type": "object", "required": ["file"], "title": "Body_upload_child_image_users_children_images__child_id__put"}, "Body_upload_milestone_group_image_admin_milestone_group_images__milestone_group_id__put": {"properties": {"file": {"type": "string", "format": "binary", "title": "File"}}, "type": "object", "required": ["file"], "title": "Body_upload_milestone_group_image_admin_milestone_group_images__milestone_group_id__put"}, "Body_upload_milestone_image_admin_milestone_images__milestone_id__post": {"properties": {"file": {"type": "string", "format": "binary", "title": "File"}}, "type": "object", "required": ["file"], "title": "Body_upload_milestone_image_admin_milestone_images__milestone_id__post"}, "Body_verify_request_token_auth_request_verify_token_post": {"properties": {"email": {"type": "string", "format": "email", "title": "Email"}}, "type": "object", "required": ["email"], "title": "Body_verify_request_token_auth_request_verify_token_post"}, "Body_verify_verify_auth_verify_post": {"properties": {"token": {"type": "string", "title": "Token"}}, "type": "object", "required": ["token"], "title": "Body_verify_verify_auth_verify_post"}, "ChildAnswerPublic": {"properties": {"answer": {"type": "string", "title": "Answer"}, "additional_answer": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Additional Answer"}, "question_id": {"type": "integer", "title": "Question Id"}}, "type": "object", "required": ["answer", "additional_answer", "question_id"], "title": "ChildAnswerPublic"}, "ChildCreate": {"properties": {"name": {"type": "string", "title": "Name", "default": ""}, "birth_year": {"type": "integer", "title": "Birth Year"}, "birth_month": {"type": "integer", "title": "Birth Month"}}, "type": "object", "required": ["birth_year", "birth_month"], "title": "ChildCreate"}, "ChildPublic": {"properties": {"name": {"type": "string", "title": "Name", "default": ""}, "birth_year": {"type": "integer", "title": "Birth Year"}, "birth_month": {"type": "integer", "title": "Birth Month"}, "id": {"type": "integer", "title": "Id"}, "has_image": {"type": "boolean", "title": "Has Image"}}, "type": "object", "required": ["birth_year", "birth_month", "id", "has_image"], "title": "ChildPublic"}, "ChildQuestionAdmin": {"properties": {"order": {"type": "integer", "title": "Order", "default": 0}, "component": {"type": "string", "title": "Component", "default": "select"}, "type": {"type": "string", "title": "Type", "default": "text"}, "options": {"type": "string", "title": "Options", "default": ""}, "additional_option": {"type": "string", "title": "Additional Option", "default": ""}, "id": {"type": "integer", "title": "Id"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/ChildQuestionText"}, "type": "object", "title": "Text", "default": {}}}, "type": "object", "required": ["id"], "title": "ChildQuestionAdmin"}, "ChildQuestionPublic": {"properties": {"id": {"type": "integer", "title": "Id"}, "component": {"type": "string", "title": "Component", "default": "select"}, "type": {"type": "string", "title": "Type", "default": "text"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/QuestionTextPublic"}, "type": "object", "title": "Text", "default": {}}, "additional_option": {"type": "string", "title": "Additional Option", "default": ""}}, "type": "object", "required": ["id"], "title": "ChildQuestionPublic"}, "ChildQuestionText": {"properties": {"question": {"type": "string", "title": "Question", "default": ""}, "options_json": {"type": "string", "title": "Options Json", "default": ""}, "options": {"type": "string", "title": "Options", "default": ""}, "child_question_id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Child Question Id"}, "lang_id": {"anyOf": [{"type": "string", "maxLength": 2}, {"type": "null"}], "title": "Lang Id"}}, "type": "object", "title": "ChildQuestionText"}, "ErrorModel": {"properties": {"detail": {"anyOf": [{"type": "string"}, {"additionalProperties": {"type": "string"}, "type": "object"}], "title": "Detail"}}, "type": "object", "required": ["detail"], "title": "ErrorModel"}, "HTTPValidationError": {"properties": {"detail": {"items": {"$ref": "#/components/schemas/ValidationError"}, "type": "array", "title": "Detail"}}, "type": "object", "title": "HTTPValidationError"}, "Language": {"properties": {"id": {"type": "string", "maxLength": 2, "title": "Id"}}, "type": "object", "required": ["id"], "title": "Language"}, "MilestoneAdmin": {"properties": {"id": {"type": "integer", "title": "Id"}, "group_id": {"type": "integer", "title": "Group Id"}, "order": {"type": "integer", "title": "Order"}, "expected_age_months": {"type": "integer", "title": "Expected Age Months"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/MilestoneText"}, "type": "object", "title": "Text", "default": {}}, "images": {"items": {"$ref": "#/components/schemas/MilestoneImage"}, "type": "array", "title": "Images", "default": []}}, "type": "object", "required": ["id", "group_id", "order", "expected_age_months"], "title": "MilestoneAdmin"}, "MilestoneAnswerPublic": {"properties": {"milestone_id": {"type": "integer", "title": "Milestone Id"}, "answer": {"type": "integer", "title": "Answer"}}, "type": "object", "required": ["milestone_id", "answer"], "title": "MilestoneAnswerPublic"}, "MilestoneAnswerSessionPublic": {"properties": {"id": {"type": "integer", "title": "Id"}, "child_id": {"type": "integer", "title": "Child Id"}, "created_at": {"type": "string", "format": "date-time", "title": "Created At"}, "answers": {"additionalProperties": {"$ref": "#/components/schemas/MilestoneAnswerPublic"}, "type": "object", "title": "Answers"}}, "type": "object", "required": ["id", "child_id", "created_at", "answers"], "title": "MilestoneAnswerSessionPublic"}, "MilestoneGroupAdmin": {"properties": {"id": {"type": "integer", "title": "Id"}, "order": {"type": "integer", "title": "Order"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/MilestoneGroupText"}, "type": "object", "title": "Text", "default": {}}, "milestones": {"items": {"$ref": "#/components/schemas/MilestoneAdmin"}, "type": "array", "title": "Milestones", "default": []}}, "type": "object", "required": ["id", "order"], "title": "MilestoneGroupAdmin"}, "MilestoneGroupPublic": {"properties": {"id": {"type": "integer", "title": "Id"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/MilestoneGroupTextPublic"}, "type": "object", "title": "Text", "default": {}}, "milestones": {"items": {"$ref": "#/components/schemas/MilestonePublic"}, "type": "array", "title": "Milestones", "default": []}}, "type": "object", "required": ["id"], "title": "MilestoneGroupPublic"}, "MilestoneGroupText": {"properties": {"title": {"type": "string", "title": "Title", "default": ""}, "desc": {"type": "string", "title": "Desc", "default": ""}, "group_id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Group Id"}, "lang_id": {"anyOf": [{"type": "string", "maxLength": 2}, {"type": "null"}], "title": "Lang Id"}}, "type": "object", "title": "MilestoneGroupText"}, "MilestoneGroupTextPublic": {"properties": {"title": {"type": "string", "title": "Title", "default": ""}, "desc": {"type": "string", "title": "Desc", "default": ""}}, "type": "object", "title": "MilestoneGroupTextPublic"}, "MilestoneImage": {"properties": {"id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Id"}, "milestone_id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Milestone Id"}, "filename": {"type": "string", "title": "Filename", "default": ""}, "approved": {"type": "boolean", "title": "Approved", "default": false}}, "type": "object", "title": "MilestoneImage"}, "MilestoneImagePublic": {"properties": {"filename": {"type": "string", "title": "Filename"}, "approved": {"type": "boolean", "title": "Approved"}}, "type": "object", "required": ["filename", "approved"], "title": "MilestoneImagePublic"}, "MilestonePublic": {"properties": {"id": {"type": "integer", "title": "Id"}, "expected_age_months": {"type": "integer", "title": "Expected Age Months"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/MilestoneTextPublic"}, "type": "object", "title": "Text", "default": {}}, "images": {"items": {"$ref": "#/components/schemas/MilestoneImagePublic"}, "type": "array", "title": "Images", "default": []}}, "type": "object", "required": ["id", "expected_age_months"], "title": "MilestonePublic"}, "MilestoneText": {"properties": {"title": {"type": "string", "title": "Title", "default": ""}, "desc": {"type": "string", "title": "Desc", "default": ""}, "obs": {"type": "string", "title": "Obs", "default": ""}, "help": {"type": "string", "title": "Help", "default": ""}, "milestone_id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Milestone Id"}, "lang_id": {"anyOf": [{"type": "string", "maxLength": 2}, {"type": "null"}], "title": "Lang Id"}}, "type": "object", "title": "MilestoneText"}, "MilestoneTextPublic": {"properties": {"title": {"type": "string", "title": "Title", "default": ""}, "desc": {"type": "string", "title": "Desc", "default": ""}, "obs": {"type": "string", "title": "Obs", "default": ""}, "help": {"type": "string", "title": "Help", "default": ""}}, "type": "object", "title": "MilestoneTextPublic"}, "QuestionTextPublic": {"properties": {"question": {"type": "string", "title": "Question", "default": ""}, "options_json": {"type": "string", "title": "Options Json", "default": ""}, "options": {"type": "string", "title": "Options", "default": ""}}, "type": "object", "title": "QuestionTextPublic"}, "UserAnswerPublic": {"properties": {"answer": {"type": "string", "title": "Answer"}, "additional_answer": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Additional Answer"}, "question_id": {"type": "integer", "title": "Question Id"}}, "type": "object", "required": ["answer", "additional_answer", "question_id"], "title": "UserAnswerPublic"}, "UserCreate": {"properties": {"email": {"type": "string", "format": "email", "title": "Email"}, "password": {"type": "string", "title": "Password"}, "is_active": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Active", "default": true}, "is_superuser": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Superuser", "default": false}, "is_verified": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Verified", "default": false}, "is_researcher": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Researcher", "default": false}}, "type": "object", "required": ["email", "password"], "title": "UserCreate"}, "UserQuestionAdmin": {"properties": {"order": {"type": "integer", "title": "Order", "default": 0}, "component": {"type": "string", "title": "Component", "default": "select"}, "type": {"type": "string", "title": "Type", "default": "text"}, "options": {"type": "string", "title": "Options", "default": ""}, "additional_option": {"type": "string", "title": "Additional Option", "default": ""}, "id": {"type": "integer", "title": "Id"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/UserQuestionText"}, "type": "object", "title": "Text", "default": {}}}, "type": "object", "required": ["id"], "title": "UserQuestionAdmin"}, "UserQuestionPublic": {"properties": {"id": {"type": "integer", "title": "Id"}, "component": {"type": "string", "title": "Component", "default": "select"}, "type": {"type": "string", "title": "Type", "default": "text"}, "text": {"additionalProperties": {"$ref": "#/components/schemas/QuestionTextPublic"}, "type": "object", "title": "Text", "default": {}}, "additional_option": {"type": "string", "title": "Additional Option", "default": ""}}, "type": "object", "required": ["id"], "title": "UserQuestionPublic"}, "UserQuestionText": {"properties": {"question": {"type": "string", "title": "Question", "default": ""}, "options_json": {"type": "string", "title": "Options Json", "default": ""}, "options": {"type": "string", "title": "Options", "default": ""}, "user_question_id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "User Question Id"}, "lang_id": {"anyOf": [{"type": "string", "maxLength": 2}, {"type": "null"}], "title": "Lang Id"}}, "type": "object", "title": "UserQuestionText"}, "UserRead": {"properties": {"id": {"type": "integer", "title": "Id"}, "email": {"type": "string", "format": "email", "title": "Email"}, "is_active": {"type": "boolean", "title": "Is Active", "default": true}, "is_superuser": {"type": "boolean", "title": "Is Superuser", "default": false}, "is_verified": {"type": "boolean", "title": "Is Verified", "default": false}, "is_researcher": {"type": "boolean", "title": "Is Researcher"}}, "type": "object", "required": ["id", "email", "is_researcher"], "title": "UserRead"}, "UserUpdate": {"properties": {"password": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Password"}, "email": {"anyOf": [{"type": "string", "format": "email"}, {"type": "null"}], "title": "Email"}, "is_active": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Active"}, "is_superuser": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Superuser"}, "is_verified": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Verified"}, "is_researcher": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Is Researcher"}}, "type": "object", "title": "UserUpdate"}, "ValidationError": {"properties": {"loc": {"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, "type": "array", "title": "Location"}, "msg": {"type": "string", "title": "Message"}, "type": {"type": "string", "title": "Error Type"}}, "type": "object", "required": ["loc", "msg", "type"], "title": "ValidationError"}}, "securitySchemes": {"APIKeyCookie": {"type": "apiKey", "in": "cookie", "name": "fastapiusersauth"}}}} diff --git a/mondey_backend/src/mondey_backend/routers/admin.py b/mondey_backend/src/mondey_backend/routers/admin.py index d90db6b6..bc5df419 100644 --- a/mondey_backend/src/mondey_backend/routers/admin.py +++ b/mondey_backend/src/mondey_backend/routers/admin.py @@ -166,6 +166,16 @@ async def upload_milestone_image( session.refresh(milestone_image) return milestone_image + @router.delete("/milestone-images/{milestone_image_id}") + async def delete_milestone_image(session: SessionDep, milestone_image_id: int): + milestone_image = get(session, MilestoneImage, milestone_image_id) + pathlib.Path( + f"{app_settings.STATIC_FILES_PATH}/m{milestone_image.id}.jpg" + ).unlink(missing_ok=True) + session.delete(milestone_image) + session.commit() + return {"ok": True} + # User question CRUD endpoints @router.get("/user-questions/", response_model=list[UserQuestionAdmin]) def get_user_questions_admin(session: SessionDep): diff --git a/mondey_backend/src/mondey_backend/routers/users.py b/mondey_backend/src/mondey_backend/routers/users.py index c4fd939b..70a7a552 100644 --- a/mondey_backend/src/mondey_backend/routers/users.py +++ b/mondey_backend/src/mondey_backend/routers/users.py @@ -100,9 +100,7 @@ async def get_child_image( f"{app_settings.PRIVATE_FILES_PATH}/children/{child.id}.jpg" ) if not image_path.exists(): - raise HTTPException(404, detail="Image not found") - if child.has_image is False: - raise HTTPException(404, detail="Child does not have an image") + image_path = pathlib.Path(f"{app_settings.DATA_FILES_PATH}/dummy.jpg") return image_path @router.put("/children-images/{child_id}") @@ -127,13 +125,10 @@ async def delete_child_image( image_path = pathlib.Path( f"{app_settings.PRIVATE_FILES_PATH}/children/{child.id}.jpg" ) - if not image_path.exists(): - raise HTTPException(404, detail="Image not found") - else: - child.has_image = False - session.commit() - image_path.unlink() - return {"ok": True} + child.has_image = False + session.commit() + image_path.unlink(missing_ok=True) + return {"ok": True} # milestone endpoints @router.get( diff --git a/mondey_backend/src/mondey_backend/settings.py b/mondey_backend/src/mondey_backend/settings.py index af2a7acd..ff8f78ea 100644 --- a/mondey_backend/src/mondey_backend/settings.py +++ b/mondey_backend/src/mondey_backend/settings.py @@ -9,6 +9,7 @@ class AppSettings(BaseSettings): model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8") # these defaults are for local development and are used if the environment variables are not set SECRET: str = "abc123" + DATA_FILES_PATH: str = "data" DATABASE_PATH: str = "db" STATIC_FILES_PATH: str = "static" PRIVATE_FILES_PATH: str = "private" diff --git a/mondey_backend/tests/conftest.py b/mondey_backend/tests/conftest.py index 2656278d..9e532931 100644 --- a/mondey_backend/tests/conftest.py +++ b/mondey_backend/tests/conftest.py @@ -2,6 +2,7 @@ import datetime import pathlib +import shutil import pytest from fastapi import FastAPI @@ -59,6 +60,16 @@ def private_dir(tmp_path_factory: pytest.TempPathFactory): return private_dir +@pytest.fixture(scope="session") +def data_dir(tmp_path_factory: pytest.TempPathFactory): + # use the same single temporary directory in all tests for private files + data_dir = tmp_path_factory.mktemp("data") + original_dummy_path = pathlib.Path(__file__).parent.parent / "data" / "dummy.jpg" + data_dir.mkdir(exist_ok=True) + shutil.copy(original_dummy_path, data_dir / "dummy.jpg") + return data_dir + + @pytest.fixture def children(): today = datetime.datetime.today() @@ -605,9 +616,10 @@ def second_active_user(): @pytest.fixture(scope="session") -def app(static_dir: pathlib.Path, private_dir: pathlib.Path): +def app(static_dir: pathlib.Path, private_dir: pathlib.Path, data_dir: pathlib.Path): settings.app_settings.STATIC_FILES_PATH = str(static_dir) settings.app_settings.PRIVATE_FILES_PATH = str(private_dir) + settings.app_settings.DATA_FILES_PATH = str(data_dir) app = create_app() return app diff --git a/mondey_backend/tests/routers/test_admin.py b/mondey_backend/tests/routers/test_admin.py index 6014e462..42eaaf7d 100644 --- a/mondey_backend/tests/routers/test_admin.py +++ b/mondey_backend/tests/routers/test_admin.py @@ -232,11 +232,11 @@ def test_post_milestone_image( assert len(admin_client.get("/milestones/4").json()["images"]) == 0 assert len(admin_client.get("/milestones/5").json()["images"]) == 0 # image ids are sequential - image_id = 3 + milestone_image_id = 3 # add an image to each milestone for milestone_id in [1, 2, 3, 4, 5]: - image_id += 1 - filename = f"m{image_id}.jpg" + milestone_image_id += 1 + filename = f"m{milestone_image_id}.jpg" static_dir_jpg = static_dir / filename assert not static_dir_jpg.is_file() with open(jpg_file, "rb") as f: @@ -252,6 +252,23 @@ def test_post_milestone_image( assert len(admin_client.get("/milestones/3").json()["images"]) == 1 assert len(admin_client.get("/milestones/4").json()["images"]) == 1 assert len(admin_client.get("/milestones/5").json()["images"]) == 1 + # remove added images + for milestone_image_id in range(4, 9): + filename = f"m{milestone_image_id}.jpg" + static_dir_jpg = static_dir / filename + assert static_dir_jpg.is_file() + assert ( + admin_client.delete( + f"/admin/milestone-images/{milestone_image_id}" + ).status_code + == 200 + ) + assert not static_dir_jpg.is_file() + assert len(admin_client.get("/milestones/1").json()["images"]) == 2 + assert len(admin_client.get("/milestones/2").json()["images"]) == 1 + assert len(admin_client.get("/milestones/3").json()["images"]) == 0 + assert len(admin_client.get("/milestones/4").json()["images"]) == 0 + assert len(admin_client.get("/milestones/5").json()["images"]) == 0 # tests for user questions diff --git a/mondey_backend/tests/routers/test_users.py b/mondey_backend/tests/routers/test_users.py index 39c52565..ca9740c0 100644 --- a/mondey_backend/tests/routers/test_users.py +++ b/mondey_backend/tests/routers/test_users.py @@ -60,9 +60,9 @@ def test_get_child_image(user_client: TestClient): assert response.content == b"2.jpg" -def test_get_child_image_no_image(user_client: TestClient): +def test_get_child_image_no_image(user_client: TestClient, data_dir: pathlib.Path): response = user_client.get("/users/children-images/1") - assert response.status_code == 404 + assert response.status_code == 200 def test_create_update_and_delete_child(user_client: TestClient): @@ -115,7 +115,8 @@ def test_upload_child_image( # child 1 does not have an image: assert not (children_dir / "1.jpg").is_file() assert user_client.get("/users/children/").json()[0]["has_image"] is False - assert user_client.get("/users/children-images/1").status_code == 404 + assert user_client.get("/users/children-images/1").status_code == 200 + # add an image for the first child with open(jpg_file, "rb") as f: response = user_client.put( @@ -145,24 +146,7 @@ def test_delete_child_image( assert response.status_code == 200 assert not (children_dir / "1.jpg").is_file() assert user_client.get("/users/children/").json()[0]["has_image"] is False - assert user_client.get("/users/children-images/1").status_code == 404 - - -def test_delete_child_image_nonexistant_path( - user_client: TestClient, private_dir: pathlib.Path, jpg_file: pathlib.Path -): - # add an image for the first child - with open(jpg_file, "rb") as f: - response = user_client.put( - "/users/children-images/1", - files={"file": ("filename", f, "image/jpeg")}, - ) - response = user_client.delete("/users/children-images/1") - assert response.status_code == 200 - - # delete the image again and observe that the image is not found - response = user_client.delete("/users/children-images/1") - assert response.status_code == 404 + assert user_client.get("/users/children-images/1").status_code == 200 def test_get_milestone_answers_child1_user_does_not_own_child(admin_client: TestClient):