mira, tengo esto:

Folder Structure:

To-do-List/
├─ .github/
│   .github/
│   └─ workflows/
│       workflows/
│       ├─ deploy.yml
│       └─ pylint.yml
├─ .gitignore
├─ docker-compose.yml
├─ FastAPI/
│   FastAPI/
│   ├─ app/
│   │   app/
│   │   ├─ .env.example
│   │   ├─ database.py
│   │   └─ main.py
│   ├─ Dockerfile
│   └─ requirements.txt
└─ MySQL/
    MySQL/
    └─ Dockerfile


File Contents:

File: To-do-List/.github/workflows/deploy.yml
=============================================
name: Deploy

on:
  push:
    branches: [ main ]

jobs:
  Deploy:
    name: Deploy to EC2
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2

    - name: Build & Deploy
      env:
        PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
        HOST_NAME: ${{ secrets.SSH_HOST }}
        USER_NAME: ${{ secrets.USER_NAME }}

      run: |
        # Guardamos la llave privada y le asignamos los permisos correctos
        echo "$PRIVATE_KEY" > private_key.pem && chmod 400 private_key.pem

        # Nos conectamos a la instancia EC2 usando SSH
        ssh -o StrictHostKeyChecking=no -i private_key.pem ${USER_NAME}@${HOST_NAME} '

        # Verificamos si el directorio es un repositorio Git
        if [ ! -d "/home/ubuntu/prod-to-do-list/.git" ]; then
          # Si no es un repositorio Git, clonamos el repositorio
          git clone https://github.com/STXVXN06/To-do-List.git /home/ubuntu/prod-to-do-list;
        fi

        # Comandos para desplegar el contenedor de Docker
        cd /home/ubuntu/prod-to-do-list &&

        # Actualizamos el repositorio
        git checkout main &&
        git fetch --all &&
        git reset --hard origin/main &&
        git pull origin main &&

        # Construimos y ejecutamos el contenedor de Docker
        docker compose down &&
        docker compose build &&
        docker compose up -d
        '


File: To-do-List/.github/workflows/pylint.yml
=============================================
name: Pylint Check

on:
  push:
    branches:
      - "**" # Se ejecuta en todas las ramas
  pull_request:
    branches:
      - "**" # Se ejecuta en pull requests desde todas las ramas

jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: "3.12"

      - name: Install dependencies from requirements.txt
        run: |
          python -m pip install --upgrade pip
          pip install -r ${{ github.workspace }}/FastAPI/requirements.txt

      - name: Run Pylint on the whole project
        run: |
          pylint ./**/*.py

      - name: Analysing the code with pylint
        run: |
          if [ ${{ steps.rate.outputs.rate }} -gt 9 ]; then
            pylint $(git ls-files '*.py')
          else
            echo "Rate is not greater than 9. Skipping pylint analysis."
          fi



File: To-do-List/.gitignore
===========================
Contenido binario o no legible.


File: To-do-List/docker-compose.yml
===================================
services:
  db:
    build: 
      context: ./MySQL
      dockerfile: Dockerfile
    container_name: database
    restart: always
    ports:
      - 3306:3306
    volumes:
      - ./MySQL/volumes:/var/lib/mysql
    hostname: to-do-list-database
    networks:
      - net_to-do-list
    healthcheck:
        test: ["CMD","mysql", "-u", "user", "-proot"]
        interval: 30s
        timeout: 5s
        retries: 5
# --------------------------------------------------------------------
  # - The adminer is a tool for managing content in databases.
  adminer:
    image: adminer
    container_name: adminer-to-do-list
    restart: always
    ports:
      - 8080:8080
    networks:
      - net_to-do-list
# --------------------------------------------------------------------
  # - fastapi refers to the container where the application backend will be stored.
  fastapi:
    build: 
      context: ./FastAPI
      dockerfile: Dockerfile
    container_name: backend
    restart: always
    volumes:
      - ./FastAPI/app:/app 
    ports:
      - "8000:8000"
    command: uvicorn main:app --reload --host 0.0.0.0 --port 80  # Recarga automática con --reload
    depends_on:
      db:
        condition: service_healthy
    networks:
      - net_to-do-list
# --------------------------------------------------------------------

networks:
  net_to-do-list:
      driver: bridge
      name: net_to-do-list



File: To-do-List/FastAPI/app/.env.example
=========================================
Contenido binario o no legible.


File: To-do-List/FastAPI/app/database.py
========================================
"""
Module for database configuration and models.
"""

import os
from dotenv import load_dotenv
from peewee import MySQLDatabase


# Load environment variables from the .env file
load_dotenv()

database = MySQLDatabase(
    os.getenv("MYSQL_DATABASE"),
    user=os.getenv("MYSQL_USER"),
    passwd=os.getenv("MYSQL_PASSWORD"),
    host=os.getenv("MYSQL_HOST"),
    port=int(os.getenv("MYSQL_PORT")),
)



File: To-do-List/FastAPI/app/main.py
====================================
"""
Main module for the FastAPI application.
"""

from contextlib import asynccontextmanager
from fastapi import FastAPI
from starlette.responses import RedirectResponse

# Routers


from database import database as connection


@asynccontextmanager
async def lifespan(api: FastAPI):  # pylint: disable=unused-argument
    """
    Manage the lifespan of the FastAPI application.

    Connects to the database at startup and closes the connection at shutdown.
    """

    # Connect to the database if the connection is closed
    if connection.is_closed():
        connection.connect()
    try:
        yield  # Application code runs here
    finally:
        #  close connection when the aplication is stop
        if not connection.is_closed:
            connection.close()


app = FastAPI(lifespan=lifespan)

# On Startup
# On Shutdown


# Documentation
@app.get("/")
async def docs():
    """
    Redirect to the documentation.
    """
    return RedirectResponse(url="/docs")


# Include routers for events and tickets



File: To-do-List/FastAPI/Dockerfile
===================================
FROM python:3.12

COPY ./app /app
COPY ./requirements.txt /app

WORKDIR /app

RUN apt-get update && apt-get upgrade -y && apt-get install -y mariadb-client && pip install mysqlclient

RUN pip install --upgrade pip
RUN pip install -r requirements.txt

CMD [ "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80" ]


File: To-do-List/FastAPI/requirements.txt
=========================================
alembic==1.13.3
annotated-types==0.7.0
anyio==4.6.0
astroid==3.3.5
black==24.10.0
click==8.1.7
dill==0.3.9
fastapi==0.115.0
greenlet==3.1.1
h11==0.14.0
idna==3.10
isort==5.13.2
Mako==1.3.5
MarkupSafe==3.0.1
mccabe==0.7.0
mypy-extensions==1.0.0
packaging==24.1
pathspec==0.12.1
peewee==3.17.6
platformdirs==4.3.6
pydantic==2.9.2
pydantic_core==2.23.4
pylint==3.3.1
PyMySQL==1.1.1
python-dotenv==1.0.1
sniffio==1.3.1
SQLAlchemy==2.0.35
starlette==0.38.6
tomlkit==0.13.2
typing_extensions==4.12.2
uvicorn==0.31.0



File: To-do-List/MySQL/Dockerfile
=================================
FROM mysql:8.0

ENV MYSQL_ROOT_PASSWORD root
ENV MYSQL_DATABASE to-do-list-database
ENV MYSQL_USER user
ENV MYSQL_PASSWORD root

EXPOSE 3306

te voy a hacer una serie de preguntas para que des respuesta en un trello de las cosas que hice y m e darás en que parte del codigo está lo que te digo, haz como un mensaje en primera persona como si fuera yo.

Tarea:

Implement user registration and login
Create API routes for user registration (POST /register) and login (POST /login).

Store password hashes securely using a hashing algorithm like bcrypt.

On login, generate and return a JWT to the client.

Validate JWT tokens on all protected endpoints.


como seria entonces