Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #40

Merged
merged 6 commits into from
Aug 13, 2024
Merged

Dev #40

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 94 additions & 20 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import Session
from starlette.exceptions import HTTPException as StarletteHTTPException
from starlette.middleware.sessions import SessionMiddleware
from sqlalchemy.exc import OperationalError
from sqlalchemy.orm import Session
from tenacity import retry, wait_fixed, stop_after_attempt
from typing import Dict, List

from app.auth import get_current_user
Expand Down Expand Up @@ -60,6 +62,29 @@ async def http_exception_handler(request: Request, exc: StarletteHTTPException):
raise exc


@retry(wait=wait_fixed(2), stop=stop_after_attempt(5))
def execute_with_retries(func, *args, **kwargs):
try:
return func(*args, **kwargs)
except OperationalError as e:
raise e

@retry(wait=wait_fixed(2), stop=stop_after_attempt(5))
def execute_write_with_retries(func, *args, **kwargs):
try:
func(*args, **kwargs)
except OperationalError as e:
raise e

def query_user(db: Session, username: str):
return db.query(User).filter(User.username == username).first()

def query_players(db: Session, current_user_id: int):
return db.query(Player).filter(Player.user_id == current_user_id).all()

def query_player(db: Session, player_id: int):
return db.query(Player).filter(Player.id == player_id).first()

@app.get("/signup", response_class=HTMLResponse)
async def signup_page(request: Request):
if request.session.get("user_id"):
Expand All @@ -74,7 +99,11 @@ async def signup(
password: str = Form(...),
db: Session = Depends(get_db),
):
user = db.query(User).filter(User.username == username).first()
try:
user = execute_with_retries(query_user, db, username)
except OperationalError:
return HTMLResponse("Error al acceder a la base de datos. Inténtalo de nuevo más tarde.", status_code=500)

if user:
return templates.TemplateResponse(request=request, name="signup.html", context={"error": "Usuario ya resgistrado"})

Expand Down Expand Up @@ -103,12 +132,10 @@ async def login(
db: Session = Depends(get_db),
):
try:
user = db.query(User).filter(User.username == username).first()
except Exception as e:
db.rollback() # Revertir cualquier cambio no confirmado
raise e
finally:
db.close()
user = execute_with_retries(query_user, db, username)
except OperationalError:
return HTMLResponse("Error al acceder a la base de datos. Inténtalo de nuevo más tarde.", status_code=500)

if not user or not user.verify_password(password):
return templates.TemplateResponse(request=request, name="login.html", context={"error": "Usuario o contraseña incorrectos"})

Expand All @@ -129,7 +156,10 @@ async def get_form(
return RedirectResponse("/login", status_code=302)

current_user_id = current_user.id
players = db.query(Player).filter(Player.user_id == current_user_id).all()
try:
players = execute_with_retries(query_players, db, current_user_id)
except OperationalError:
return HTMLResponse("Error al acceder a la base de datos. Inténtalo de nuevo más tarde.", status_code=500)

context = {"players": players}

Expand Down Expand Up @@ -175,7 +205,11 @@ async def submit_form(request: Request, db: Session = Depends(get_db), current_u
player_data.append(player)

# Guardar o actualizar jugadores en la base de datos
existing_players = db.query(Player).filter(Player.user_id == current_user_id).all()
try:
existing_players = execute_with_retries(query_players, db, current_user_id)
except OperationalError:
return HTMLResponse("Error al acceder a la base de datos. Inténtalo de nuevo más tarde.", status_code=500)

existing_players_dict = {player.name: player for player in existing_players}

players_to_add = []
Expand Down Expand Up @@ -225,7 +259,11 @@ async def submit_form(request: Request, db: Session = Depends(get_db), current_u
start_time_3 = time.time()

# Calculate the total and average skills for each team
players = db.query(Player).filter(Player.user_id == current_user_id).all()
try:
players = execute_with_retries(query_players, db, current_user_id)
except OperationalError:
return HTMLResponse("Error al acceder a la base de datos. Inténtalo de nuevo más tarde.", status_code=500)

player_data_dict = {player.name: player for player in players}

for team in teams:
Expand Down Expand Up @@ -269,38 +307,74 @@ async def submit_form(request: Request, db: Session = Depends(get_db), current_u
@app.get("/reset")
async def reset_session(db: Session = Depends(get_db), current_user: User = Depends(get_current_user)):
current_user_id = current_user.id
db.query(Player).filter(Player.user_id == current_user_id).delete()
db.commit()

def delete_players():
db.query(Player).filter(Player.user_id == current_user_id).delete()
db.commit()

try:
execute_write_with_retries(delete_players)
except OperationalError:
return {"error": "Error al acceder a la base de datos. Inténtalo de nuevo más tarde."}

return {"ok": True}


@app.get("/player/{player_id}")
def get_player(player_id: int, db: Session = Depends(get_db)):
player = db.query(Player).filter(Player.id == player_id).first()
try:
player = execute_with_retries(query_player, db, player_id)
except OperationalError:
return HTMLResponse("Error al acceder a la base de datos. Inténtalo de nuevo más tarde.", status_code=500)

if player is None:
raise HTTPException(status_code=404, detail="Player not found")
return player


@app.put("/player/{player_id}")
def update_player(player_id: int, player: PlayerCreate, db: Session = Depends(get_db)):
db_player = db.query(Player).filter(Player.id == player_id).first()
try:
db_player = execute_with_retries(query_player, db, player_id)
except OperationalError:
return HTMLResponse("Error al acceder a la base de datos. Inténtalo de nuevo más tarde.", status_code=500)

if db_player is None:
raise HTTPException(status_code=404, detail="Player not found")
for key, value in player.model_dump().items():
setattr(db_player, key, value)
db.commit()
db.refresh(db_player)

def update_and_commit():
db.commit()
db.refresh(db_player)

try:
execute_write_with_retries(update_and_commit)
except OperationalError:
return HTMLResponse("Error al realizar la actualización. Inténtalo de nuevo más tarde.", status_code=500)

return db_player


@app.delete("/player/{player_id}")
def delete_player(player_id: int, db: Session = Depends(get_db)):
player = db.query(Player).filter(Player.id == player_id).first()
try:
player = execute_with_retries(query_player, db, player_id)
except OperationalError:
return HTMLResponse("Error al acceder a la base de datos. Inténtalo de nuevo más tarde.", status_code=500)

if player is None:
raise HTTPException(status_code=404, detail="Player not found")
db.delete(player)
db.commit()

def delete_player():
db.delete(player)
db.commit()

try:
execute_write_with_retries(delete_player)
except OperationalError:
return HTMLResponse("Error al eliminar el jugador. Inténtalo de nuevo más tarde.", status_code=500)

return {"ok": True}

@app.get("/logout")
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ SQLAlchemy==2.0.31
starlette==0.37.2
itsdangerous
sqlalchemy-libsql
colorlog
tenacity
colorlog
25 changes: 3 additions & 22 deletions templates/500.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,37 +28,18 @@
font-weight: bold;
margin-top: 10px;
}
.icon {
font-size: 3rem;
margin-bottom: 10px;
}
.message {
margin-top: 20px;
font-size: 1.2rem;
}
.contact-button {
margin-top: 10px;
padding: 10px 20px;
font-size: 1rem;
color: #ffffff;
background-color: #721c24;
border: none;
border-radius: 5px;
cursor: pointer;
}
.contact-button:hover {
background-color: #d3d3d3;
color: #721c24;
}
</style>
</head>
<body>
<div class="container">
<h1>500 - Error del servidor</h1>
<p>Lo sentimos, tuvimos un problema en el servidor.</p>
<p>Serás redirigido al login en <span id="countdown" class="countdown">10</span> segundos...</p>
<p class="message">Si sigues teniendo este problema, por favor comunícate con el creador del sitio.</p>
<a href="mailto:fedecarboni7@gmail.com" class="contact-button">Enviar email</a>
<p>Disculpanos, tuvimos un problema en el servidor.</p>
<p>Serás redirigido en <span id="countdown" class="countdown">10</span> segundos...</p>
<p class="message">Si sigues teniendo este problema, por favor probá vaciando la memoria caché, o volvé a intentar más tarde.</p>
</div>
<script>
let countdownElement = document.getElementById('countdown');
Expand Down
4 changes: 2 additions & 2 deletions templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,8 @@ <h2>Equipo 2</h2>
<footer class="footer">
<div class="footer-links">
<a class="footer-link" href="mailto:fedecarboni7@gmail.com"><i class="fa-regular fa-comment"></i></a>
<a class="footer-link" href="https://www.linkedin.com/in/federicocarboni7/" target="_blank"><i class="fa-brands fa-linkedin"></i></a>
<a class="footer-link" href="https://github.com/fedecarboni7" target="_blank"><i class="fa-brands fa-github"></i></a>
<a class="footer-link" href="https://www.linkedin.com/in/federicocarboni7/" target="_blank" rel="noopener noreferrer"><i class="fa-brands fa-linkedin"></i></a>
<a class="footer-link" href="https://github.com/fedecarboni7" target="_blank" rel="noopener noreferrer"><i class="fa-brands fa-github"></i></a>
</div>
<p class="copyright">© 2024 fedecarboni7</p>
</footer>
Expand Down
Loading