diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 56d305f2..8e965edd 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -81,6 +81,14 @@ jobs: env: MP_SMTP_AUTH_ACCEPT_ANY: 1 MP_SMTP_AUTH_ALLOW_INSECURE: 1 + services: + mailpit: + image: axllent/mailpit + ports: + - 1025:1025 + env: + MP_SMTP_AUTH_ACCEPT_ANY: 1 + MP_SMTP_AUTH_ALLOW_INSECURE: 1 test-frontend-format: name: Test Frontend Formatting diff --git a/backend/src/config.py b/backend/src/config.py index 069ba1f4..07945582 100644 --- a/backend/src/config.py +++ b/backend/src/config.py @@ -1,6 +1,7 @@ import os from datetime import datetime from smtplib import SMTP +from smtplib import SMTP import boto3 from fastapi.security import OpenIdConnect diff --git a/backend/src/router.py b/backend/src/router.py index 7325b113..fe2a2f54 100644 --- a/backend/src/router.py +++ b/backend/src/router.py @@ -2,6 +2,7 @@ import os import time from typing import Annotated, Union +from typing import Annotated, Union from uuid import uuid4 from basegun_ml.classification import get_typology @@ -11,6 +12,7 @@ BackgroundTasks, Cookie, Depends, + Depends, File, Form, HTTPException, @@ -24,6 +26,8 @@ from .config import APP_VERSION, S3_PREFIX, TYPOLOGIES_MEASURED, get_base_logs from .models import EmailData from .utils import get_current_user, send_mail, upload_image +from .models import EmailData +from .utils import get_current_user, send_mail, upload_image router = APIRouter(prefix="/api") diff --git a/backend/src/utils.py b/backend/src/utils.py index ba7b05a2..f7d919ee 100644 --- a/backend/src/utils.py +++ b/backend/src/utils.py @@ -56,7 +56,7 @@ async def get_current_user(token: Annotated[str, Depends(OAUTH2_SCHEME)]): token.split()[1], PUBLIC_KEY, algorithms=["RS256"], - audience=["master-realm", "account"], + # audience=["master-realm", "account"], ) except jwt.InvalidTokenError: raise credentials_exception diff --git a/backend/tests/test_api.py b/backend/tests/test_api.py index 11b25701..0c5c457b 100644 --- a/backend/tests/test_api.py +++ b/backend/tests/test_api.py @@ -119,6 +119,7 @@ def test_headers(self): assert header_to_add["name"].lower() in CURRENT_HEADERS + class TestUpload: def test_revolver_without_card(self): with open("./tests/revolver.jpg", "rb") as f: diff --git a/frontend/src/api/api-client.ts b/frontend/src/api/api-client.ts new file mode 100644 index 00000000..f6471ea4 --- /dev/null +++ b/frontend/src/api/api-client.ts @@ -0,0 +1,52 @@ +/* eslint-disable camelcase */ +import axios from "axios"; +import { + ASK_FOR_OPINION_ROUTE, + IDENTIFICATION_DUMMY_ROUTE, + IDENTIFICATION_FEEDBACK_ROUTE, + TUTORIAL_FEEDBACK_ROUTE, + UPLOAD_PHOTO_FOR_DETECTION_ROUTE, +} from "./api-routes"; + +export const uploadPhotoForDetection = async (file: File) => { + const fd = new FormData(); + fd.append("image", file, file.name); + fd.append("date", "" + Date.now() / 1000); // date.now gives in milliseconds, convert to seconds + + const { data } = await axios.post(UPLOAD_PHOTO_FOR_DETECTION_ROUTE, fd); + return data; +}; + +export const sendTutorialFeedback = async (feedback: any) => { + const { data } = await axios.post(TUTORIAL_FEEDBACK_ROUTE, feedback); + return data; +}; + +export const sendIdentificationFeedback = async (feedbackData: any) => { + const { data } = await axios.post( + IDENTIFICATION_FEEDBACK_ROUTE, + feedbackData, + ); + return data; +}; + +export const sendIdentificationDummyFeedback = async (feedbackDummy: any) => { + const { data } = await axios.post(IDENTIFICATION_DUMMY_ROUTE, feedbackDummy); + return data; +}; + +export const sendExpertiseForm = async ( + feedbackExpert: any, + accessToken: string, +) => { + try { + const { data } = await axios.post(ASK_FOR_OPINION_ROUTE, feedbackExpert, { + headers: { + Authorization: `Bearer ${accessToken}`, + }, + }); + return data; + } catch (error) { + console.error("Erreur lors de l'envoi du formulaire :", error); + } +}; diff --git a/frontend/src/api/api-routes.ts b/frontend/src/api/api-routes.ts new file mode 100644 index 00000000..f134236c --- /dev/null +++ b/frontend/src/api/api-routes.ts @@ -0,0 +1,5 @@ +export const UPLOAD_PHOTO_FOR_DETECTION_ROUTE = "/upload"; +export const TUTORIAL_FEEDBACK_ROUTE = "/tutorial-feedback"; +export const IDENTIFICATION_FEEDBACK_ROUTE = "/identification-feedback"; +export const IDENTIFICATION_DUMMY_ROUTE = "/identification-dummy"; +export const ASK_FOR_OPINION_ROUTE = "/expert-contact"; diff --git a/frontend/src/components/ContactExpert.vue b/frontend/src/components/ContactExpert.vue index 4a673712..fba1b85d 100644 --- a/frontend/src/components/ContactExpert.vue +++ b/frontend/src/components/ContactExpert.vue @@ -7,7 +7,7 @@ href="#" icon="ri-alert-line" label="Contacter un expert" - @click="$router.push({ name: 'ExpertSituationGN' })" + @click="$router.push({ name: 'ExpertSituation' })" /> diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index ebd4ffe7..8641744f 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -9,6 +9,7 @@ import { clearLocalStorage } from "@/utils/storage-utils.js"; import { mgr } from "@/utils/authentication"; import MissingCardPage from "@/views/MissingCardPage.vue"; +import ExpertiseForm from "@/views/GuideAskingExpertise/ExpertiseForm.vue"; const HomePage = () => import("@/views/HomePage.vue"); const StartPage = () => import("@/views/StartPage.vue"); @@ -194,30 +195,33 @@ const routes: RouteRecordRaw[] = [ wholeLogo: true, }, }, - - // tutorial to contact expert { - path: "/guide-contact-pn", - name: "ExpertSituationPN", + path: "/guide-contact", + name: "ExpertSituation", component: ExpertSituation, + beforeEnter: (to, from, next) => { + mgr.getUser().then((user) => { + console.log(user); + if (user === null) { + mgr.signinRedirect(); + } else { + next(); + } + }); + }, }, { - path: "/guide-contact-gn", - name: "ExpertSituationGN", - component: ExpertSituation, - beforeEnter: (to, from) => { + path: "/guide-demande-expertise", + name: "ExpertiseForm", + component: ExpertiseForm, + beforeEnter: (to, from, next) => { mgr.getUser().then((user) => { console.log(user); - if (user === null) - mgr - .signinRedirect() - .then((data) => console.log(data)) - .catch((err) => { - console.log(err); - return { - name: "PageNotFound", - }; - }); + if (user === null) { + mgr.signinRedirect(); + } else { + next(); + } }); }, }, @@ -234,10 +238,19 @@ const routes: RouteRecordRaw[] = [ { path: "callback", name: "AuthCallback", - beforeEnter: (to, from) => { - mgr.signinCallback(); - mgr.getUser().then((user) => console.log(user)); - return { name: "ExpertSituationGN" }; + beforeEnter: async (to, from, next) => { + try { + await mgr.signinRedirectCallback(); + const user = await mgr.getUser(); + if (user !== null) { + next({ name: "ExpertSituation" }); + } else { + next({ name: "AuthRedirect" }); + } + } catch (error) { + console.error("Erreur signin callback:", error); + next({ name: "AuthRedirect" }); + } }, }, ], diff --git a/frontend/src/utils/authentication.ts b/frontend/src/utils/authentication.ts index e754bb78..fe29a46b 100644 --- a/frontend/src/utils/authentication.ts +++ b/frontend/src/utils/authentication.ts @@ -6,7 +6,8 @@ export const mgr = new UserManager({ authority: import.meta.env.VITE_OIDC_AUTHORITY, client_id: import.meta.env.VITE_OIDC_CLIENT_ID, redirect_uri: `${FRONTEND_URL}/auth/callback`, - silent_redirect_uri: `${FRONTEND_URL}`, post_logout_redirect_uri: `${FRONTEND_URL}`, response_type: "code", + scope: "openid profile email", + automaticSilentRenew: false, }); diff --git a/frontend/src/views/GuideAskingExpertise/ExpertiseForm.vue b/frontend/src/views/GuideAskingExpertise/ExpertiseForm.vue new file mode 100644 index 00000000..60a8eb64 --- /dev/null +++ b/frontend/src/views/GuideAskingExpertise/ExpertiseForm.vue @@ -0,0 +1,602 @@ + + + + + diff --git a/frontend/src/views/GuideContactExpert/ExpertSituation.vue b/frontend/src/views/GuideContactExpert/ExpertSituation.vue index 761c8a12..721f18a2 100644 --- a/frontend/src/views/GuideContactExpert/ExpertSituation.vue +++ b/frontend/src/views/GuideContactExpert/ExpertSituation.vue @@ -1,58 +1,28 @@