diff --git a/Backend/FastAPI/db/client.py b/Backend/FastAPI/db/client.py index bfccb67b..1b06c558 100644 --- a/Backend/FastAPI/db/client.py +++ b/Backend/FastAPI/db/client.py @@ -1,26 +1,3 @@ -# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480) - -### MongoDB client ### - -# Descarga versión community: https://www.mongodb.com/try/download -# Instalación:https://www.mongodb.com/docs/manual/tutorial -# Módulo conexión MongoDB: pip install pymongo -# Ejecución: sudo mongod --dbpath "/path/a/la/base/de/datos/" -# Conexión: mongodb://localhost - from pymongo import MongoClient -# Descomentar el db_client local o remoto correspondiente - -# Base de datos local MongoDB -db_client = MongoClient().local - -# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=25470 - -# Base de datos remota MongoDB Atlas (https://mongodb.com) -# db_client = MongoClient( -# "mongodb+srv://:@/?retryWrites=true&w=majority").test - -# Despliegue API en la nube: -# Deta - https://www.deta.sh/ -# Intrucciones - https://fastapi.tiangolo.com/deployment/deta/ +db_client = MongoClient() \ No newline at end of file diff --git a/Backend/FastAPI/db/schemas/user.py b/Backend/FastAPI/db/schemas/user.py index cdfdcd56..1fa12355 100644 --- a/Backend/FastAPI/db/schemas/user.py +++ b/Backend/FastAPI/db/schemas/user.py @@ -1,7 +1,3 @@ -# Clase en vídeo (22/12/2022): https://www.twitch.tv/videos/1686104006 - -### User schema ### - def user_schema(user) -> dict: return {"id": str(user["_id"]), "username": user["username"], diff --git a/Backend/FastAPI/main.py b/Backend/FastAPI/main.py index 09d72fa5..c9d6aa3e 100644 --- a/Backend/FastAPI/main.py +++ b/Backend/FastAPI/main.py @@ -1,50 +1,37 @@ -# Clase en vídeo: https://youtu.be/_y9qQZXE24A - -### Hola Mundo ### - -# Documentación oficial: https://fastapi.tiangolo.com/es/ - -# Instala FastAPI: pip install "fastapi[all]" - from fastapi import FastAPI from routers import products, users, basic_auth_users, jwt_auth_users, users_db from fastapi.staticfiles import StaticFiles app = FastAPI() -# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=12475 +# Routers app.include_router(products.router) app.include_router(users.router) -# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=14094 app.include_router(basic_auth_users.router) - -# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=17664 app.include_router(jwt_auth_users.router) - -# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480 app.include_router(users_db.router) -# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=13618 -app.mount("/static", StaticFiles(directory="static"), name="static") +app.mount("/static", StaticFiles(directory = "static"), name = "static") -# Url local: http://127.0.0.1:8000 - +# @: decorador de operaciones de path +# Métodos o operaciones de HTTP: GET, POST, PUT, DELETE +# async: para realizar la operacion en segundo plano al llamar a un servidor -@app.get("/") +# Url local: http://127.0.0.1:8000 +@app.get("/") # esta es la raiz donde se despliega async def root(): - return "Hola FastAPI!" + return "¡Hola FastAPI!" # Url local: http://127.0.0.1:8000/url - - -@app.get("/url") +@app.get("/url") # esta es la raiz donde se despliega async def url(): - return {"url": "https://mouredev.com/python"} + return { "url_curso":"https://mouredev.com/python" } + # Inicia el server: uvicorn main:app --reload # Detener el server: CTRL+C # Documentación con Swagger: http://127.0.0.1:8000/docs -# Documentación con Redocly: http://127.0.0.1:8000/redoc +# Documentación con Redocly: http://127.0.0.1:8000/redoc \ No newline at end of file diff --git a/Backend/FastAPI/routers/basic_auth_users.py b/Backend/FastAPI/routers/basic_auth_users.py index 054b991d..1b5d9dab 100644 --- a/Backend/FastAPI/routers/basic_auth_users.py +++ b/Backend/FastAPI/routers/basic_auth_users.py @@ -1,88 +1,72 @@ -# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=14094 - -### Users API con autorización OAuth2 básica ### - -from fastapi import APIRouter, Depends, HTTPException, status +from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm -router = APIRouter(prefix="/basicauth", - tags=["basicauth"], - responses={status.HTTP_404_NOT_FOUND: {"message": "No encontrado"}}) +# OAuth2PasswordBearer = se encarga de gestionar el usuario y contraseña de autenticacion +# OAuth2PasswordRequestForm = forma en la que se va a enviar a nuestro backend estos criterios de autenticacion -oauth2 = OAuth2PasswordBearer(tokenUrl="login") +router = APIRouter() +oauth2 = OAuth2PasswordBearer(tokenUrl = "login") -class User(BaseModel): - username: str +class User(BaseModel): + username: str full_name: str - email: str + email: str disabled: bool - class UserDB(User): password: str - users_db = { - "mouredev": { - "username": "mouredev", - "full_name": "Brais Moure", - "email": "braismoure@mourede.com", + "leonardo": { + "username": "leoulffe", + "full_name": "Leonardo Ulffe", + "email": "leonardo.ulffe.2003@gmail.com", "disabled": False, "password": "123456" }, - "mouredev2": { - "username": "mouredev2", - "full_name": "Brais Moure 2", - "email": "braismoure2@mourede.com", + "leonardo2": { + "username": "leoulffe2", + "full_name": "Leonardo Ulffe2", + "email": "leonardo.ulffe.2003@gmail.com", "disabled": True, "password": "654321" } } - def search_user_db(username: str): if username in users_db: return UserDB(**users_db[username]) - def search_user(username: str): if username in users_db: return User(**users_db[username]) - - + async def current_user(token: str = Depends(oauth2)): user = search_user(token) if not user: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Credenciales de autenticación inválidas", - headers={"WWW-Authenticate": "Bearer"}) - + raise HTTPException(status_code=401, detail = "Credenciales de autenticacion inválidas", + headers = {"WWW-Authenticate":"Bearer"}) + if user.disabled: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="Usuario inactivo") - + raise HTTPException(status_code=400, detail = "Usuario inactivo") + return user @router.post("/login") async def login(form: OAuth2PasswordRequestForm = Depends()): user_db = users_db.get(form.username) - if not user_db: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, detail="El usuario no es correcto") - - user = search_user_db(form.username) + if not users_db: + raise HTTPException(status_code=400, detail = "El usuario no es correcto") + + user = search_user(form.username) if not form.password == user.password: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, detail="La contraseña no es correcta") - - return {"access_token": user.username, "token_type": "bearer"} + raise HTTPException(status_code=400, detail = "La contraseña no es correcta") + return {"access_token" : user.username, "token_type" : "bearer"} @router.get("/users/me") async def me(user: User = Depends(current_user)): - return user + return user \ No newline at end of file diff --git a/Backend/FastAPI/routers/jwt_auth_users.py b/Backend/FastAPI/routers/jwt_auth_users.py index c942b0c6..cedfb366 100644 --- a/Backend/FastAPI/routers/jwt_auth_users.py +++ b/Backend/FastAPI/routers/jwt_auth_users.py @@ -34,19 +34,19 @@ class UserDB(User): users_db = { - "mouredev": { - "username": "mouredev", - "full_name": "Brais Moure", - "email": "braismoure@mourede.com", + "leonardo": { + "username": "leoulffe", + "full_name": "Leonardo Ulffe", + "email": "leonardo.ulffe.2003@gmail.com", "disabled": False, - "password": "$2a$12$B2Gq.Dps1WYf2t57eiIKjO4DXC3IUMUXISJF62bSRiFfqMdOI2Xa6" + "password": "123456" }, - "mouredev2": { - "username": "mouredev2", - "full_name": "Brais Moure 2", - "email": "braismoure2@mourede.com", + "leonardo2": { + "username": "leoulffe2", + "full_name": "Leonardo Ulffe2", + "email": "leonardo.ulffe.2003@gmail.com", "disabled": True, - "password": "$2a$12$SduE7dE.i3/ygwd0Kol8bOFvEABaoOOlC8JsCSr6wpwB4zl5STU4S" + "password": "654321" } } diff --git a/Backend/FastAPI/routers/products.py b/Backend/FastAPI/routers/products.py index 6d85b336..502e28b8 100644 --- a/Backend/FastAPI/routers/products.py +++ b/Backend/FastAPI/routers/products.py @@ -1,22 +1,13 @@ -# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=12475 - -### Products API ### - from fastapi import APIRouter -router = APIRouter(prefix="/products", - tags=["products"], - responses={404: {"message": "No encontrado"}}) - -products_list = ["Producto 1", "Producto 2", - "Producto 3", "Producto 4", "Producto 5"] +router = APIRouter(prefix = "/products", tags = ["products"],responses = {404: {"message": "No encontrado"}}) +products_list = ["Producto 1", "Producto 2", "Producto 3", "Producto 4", "Producto 5"] @router.get("/") async def products(): return products_list - @router.get("/{id}") async def products(id: int): - return products_list[id] + return products_list[id] \ No newline at end of file diff --git a/Backend/FastAPI/routers/users.py b/Backend/FastAPI/routers/users.py index 46aca70c..0b77267a 100644 --- a/Backend/FastAPI/routers/users.py +++ b/Backend/FastAPI/routers/users.py @@ -1,65 +1,52 @@ -# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=5382 - -### Users API ### - from fastapi import APIRouter, HTTPException -from pydantic import BaseModel - -# Inicia el server: uvicorn users:app --reload +from pydantic import BaseModel # Para modelar un objeto router = APIRouter() +# Inicia el server: uvicorn users:app --reload -class User(BaseModel): - id: int - name: str +# Entidad user +class User(BaseModel): # El BaseModel nos da la capacidad de crear una entidad + id: int # recomendacion de tiparlo + name: str surname: str url: str age: int +users_list = [User(id = 1, name = "Leonardo", surname = "Ulffe", url = "https://google.com", age = 21), + User(id = 2, name = "Josue", surname = "Torres", url = "https://x.com", age = 30), + User(id = 3, name = "Leo", surname = "Uribe", url = "https://facebook.com", age = 19)] -users_list = [User(id=1, name="Brais", surname="Moure", url="https://moure.dev", age=35), - User(id=2, name="Moure", surname="Dev", - url="https://mouredev.com", age=35), - User(id=3, name="Brais", surname="Dahlberg", url="https://haakon.com", age=33)] - - -@router.get("/usersjson") -async def usersjson(): # Creamos un JSON a mano - return [{"name": "Brais", "surname": "Moure", "url": "https://moure.dev", "age": 35}, - {"name": "Moure", "surname": "Dev", - "url": "https://mouredev.com", "age": 35}, - {"name": "Haakon", "surname": "Dahlberg", "url": "https://haakon.com", "age": 33}] +# Url local: http://127.0.0.1:8000 +@router.get("/usersjson") # esta es la raiz donde se despliega +async def usersjson(): + return [{"name": "Leonardo", "surname": "Ulffe", "url": "https://google.com", "age": 21}, + {"name": "Josue", "surname": "Torres", "url": "https://x.com", "age": 30}, + {"name": "Leo", "surname": "Uribe", "url": "https://facebook.com", "age": 19}] - -@router.get("/users") +@router.get("/users") # esta es la raiz donde se despliega async def users(): return users_list - -@router.get("/user/{id}") # Path +# Path +@router.get("/user/{id}") # esta es la raiz donde se despliega async def user(id: int): return search_user(id) - -@router.get("/user/") # Query +# Query +@router.get("/user/") # Parametro de Query async def user(id: int): return search_user(id) - - -# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=8529 - - -@router.post("/user/", response_model=User, status_code=201) + +@router.post("/user/", response_model=User, status_code=201) async def user(user: User): if type(search_user(user.id)) == User: - raise HTTPException(status_code=404, detail="El usuario ya existe") - - users_list.append(user) - return user - + raise HTTPException(status_code=404, detail = "El usuario ya existe") + else: + users_list.append(user) + return user -@router.put("/user/") +@router.put("/user/") async def user(user: User): found = False @@ -68,13 +55,12 @@ async def user(user: User): if saved_user.id == user.id: users_list[index] = user found = True - + if not found: return {"error": "No se ha actualizado el usuario"} - - return user - - + else: + return user + @router.delete("/user/{id}") async def user(id: int): @@ -84,9 +70,10 @@ async def user(id: int): if saved_user.id == id: del users_list[index] found = True - + if not found: - return {"error": "No se ha eliminado el usuario"} + return {"error": "No se ha encontrado el usuario"} + def search_user(id: int): @@ -94,4 +81,5 @@ def search_user(id: int): try: return list(users)[0] except: - return {"error": "No se ha encontrado el usuario"} + return {"error": "No se ha encontrado un usuario"} + diff --git a/Backend/FastAPI/routers/users_db.py b/Backend/FastAPI/routers/users_db.py index 7e61d751..86c7dcd6 100644 --- a/Backend/FastAPI/routers/users_db.py +++ b/Backend/FastAPI/routers/users_db.py @@ -1,7 +1,3 @@ -# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480 - -### Users DB API ### - from fastapi import APIRouter, HTTPException, status from db.models.user import User from db.schemas.user import user_schema, users_schema @@ -37,9 +33,9 @@ async def user(user: User): user_dict = dict(user) del user_dict["id"] - id = db_client.users.insert_one(user_dict).inserted_id + id = db_client.local.users.insert_one(user_dict).inserted_id - new_user = user_schema(db_client.users.find_one({"_id": id})) + new_user = user_schema(db_client.local.users.find_one({"_id": id})) return User(**new_user) diff --git a/Backend/FastAPI/static/images/motivation.jpg b/Backend/FastAPI/static/images/motivation.jpg new file mode 100644 index 00000000..f9a0da9a Binary files /dev/null and b/Backend/FastAPI/static/images/motivation.jpg differ diff --git a/Backend/FastAPI/static/images/python.jpg b/Backend/FastAPI/static/images/python.jpg deleted file mode 100644 index 0be1c65e..00000000 Binary files a/Backend/FastAPI/static/images/python.jpg and /dev/null differ diff --git a/Backend/type_hints.py b/Backend/type_hints.py index 42b7c01a..97967066 100644 --- a/Backend/type_hints.py +++ b/Backend/type_hints.py @@ -2,6 +2,7 @@ ### Type Hints ### +# Python es de tipado dinámico my_string_variable = "My String variable" print(my_string_variable) print(type(my_string_variable))