Skip to content

Commit

Permalink
feat: 🛂 implement rate limit on api requests
Browse files Browse the repository at this point in the history
  • Loading branch information
nutfdt committed Dec 19, 2024
1 parent 2b104f5 commit df46a8d
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 9 deletions.
1 change: 1 addition & 0 deletions backend/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ boto3==1.35.81
autodynatrace==2.1.1
PyJWT==2.10.1
cryptography==44.0.0
slowapi===0.1.9
# ML
basegun-ml==2.0.5
numpy<3.0.0
Expand Down
6 changes: 6 additions & 0 deletions backend/src/main.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.errors import RateLimitExceeded
from slowapi.util import get_remote_address

from .config import HEADERS
from .router import router

limiter = Limiter(key_func=get_remote_address)
app = FastAPI(docs_url="/api/docs")
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)

app.add_middleware(
CORSMiddleware,
Expand Down
16 changes: 15 additions & 1 deletion backend/src/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
status,
)
from fastapi.responses import PlainTextResponse
from slowapi import Limiter
from slowapi.util import get_remote_address
from user_agents import parse

from .config import (
Expand All @@ -35,21 +37,26 @@
from .utils import get_current_user, send_mail, upload_image

router = APIRouter(prefix="/api")
limiter = Limiter(key_func=get_remote_address)


@router.get("/", response_class=PlainTextResponse)
@limiter.limit("5/minute")
def home():
return "Basegun backend"


@router.get("/version", response_class=PlainTextResponse)
def version():
@limiter.limit("5/minute")
def version(request: Request):
return APP_VERSION


@router.get("/contact-details")
@limiter.limit("5/minute")
async def phone_number(
current_user: Annotated[dict, Depends(get_current_user)],
request: Request,
):
if current_user.get("idp") != "proxyma":
raise HTTPException(
Expand All @@ -63,6 +70,7 @@ async def phone_number(


@router.post("/upload")
@limiter.limit("5/minute")
async def imageupload(
request: Request,
response: Response,
Expand Down Expand Up @@ -141,6 +149,7 @@ async def imageupload(


@router.post("/identification-feedback")
@limiter.limit("5/minute")
async def log_feedback(request: Request, user_id: Union[str, None] = Cookie(None)):
res = await request.json()

Expand All @@ -155,6 +164,7 @@ async def log_feedback(request: Request, user_id: Union[str, None] = Cookie(None


@router.post("/tutorial-feedback")
@limiter.limit("5/minute")
async def log_tutorial_feedback(
request: Request, user_id: Union[str, None] = Cookie(None)
):
Expand All @@ -178,7 +188,9 @@ async def log_tutorial_feedback(


@router.post("/expert-contact")
@limiter.limit("5/minute")
async def expert_contact(
request: Request,
firstname: Annotated[str, Form()],
lastname: Annotated[str, Form()],
nigend: Annotated[str, Form()],
Expand Down Expand Up @@ -219,7 +231,9 @@ async def expert_contact(


@router.post("/identification-alarm-gun")
@limiter.limit("5/minute")
async def image_alarm_gun(
request: Request,
image: UploadFile = File(...),
):
try:
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ declare module 'vue' {
DsfrAlert: typeof import('@gouvminint/vue-dsfr')['DsfrAlert']
DsfrButton: typeof import('@gouvminint/vue-dsfr')['DsfrButton']
DsfrCheckbox: typeof import('@gouvminint/vue-dsfr')['DsfrCheckbox']
DsfrErrorPage: typeof import('@gouvminint/vue-dsfr')['DsfrErrorPage']
DsfrFileUpload: typeof import('@gouvminint/vue-dsfr')['DsfrFileUpload']
DsfrHeader: typeof import('@gouvminint/vue-dsfr')['DsfrHeader']
DsfrInput: typeof import('@gouvminint/vue-dsfr')['DsfrInput']
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
h2 {
font-size: 1.3rem;
}

.error-img {
width: 120%;
}
}
.text-blue {
color: var(--blue-france-sun-113-625);
Expand Down
45 changes: 38 additions & 7 deletions frontend/src/views/ErrorPage.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,46 @@
<script lang="ts" setup>
import { useRoute } from "vue-router";
const route = useRoute();
const errorStatus = route.query.status || 0o0;
const errorMessage = computed(() => {
if (errorStatus == 429) {
return "Il semblerait que vous ayez effectué plusieurs requêtes en quelques minutes. Veuillez réessayer plus tard.";
} else if (errorStatus == 500) {
return "Une erreur interne lié au serveur est survenue. Veuillez réessayer plus tard.";
} else if (errorStatus == 401) {
return "Vous n'êtes pas autorisé à accéder à cette page. Veuillez vous authentifier.";
} else {
return "Une erreur est survenue. Veuillez réessayer plus tard.";
}
});
</script>

<template>
<div class="fr-container">
<div class="text-center relative top-1/6 m-4">
<h1>Erreur</h1>
<p>Une erreur est survenue dans le traitement de votre requête.</p>
<div class="text-center relative top-1/6 <md:top-4 m-4">
<DsfrErrorPage
:title="'Erreur ' + errorStatus"
subtitle=""
:description="errorMessage"
help="Si vous êtes sur cette page, c'est que vous avez rencontré un problème. Réessayer plus tard et si le problème persiste, contactez-nous."
/>

<p>
Veuillez réessayer ou
<router-link :to="{ name: 'ContactPage' }"> nous contacter </router-link
>.
Vous pouvez retourner vers la page d'accueil ou
<strong
><router-link :to="{ name: 'ContactPage' }">
nous contacter.
</router-link></strong
>
</p>
<router-link v-slot="{ navigate }" :to="{ name: 'StartPage' }">
<DsfrButton label="Retour" @click="navigate()" />
<DsfrButton
icon="ri-home-4-line"
label="Retour vers l'accueil"
@click="navigate()"
/>
</router-link>
</div>
</div>
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/views/InstructionsPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ async function uploadImage(base64: string, fileName: string) {
router.push(nextRoute);
} catch (error) {
console.log(error);
router.push({ name: "ErrorPage" });
const status = error.status;
router.push({ name: "ErrorPage", query: { status } });
}
try {
Expand Down

0 comments on commit df46a8d

Please sign in to comment.