Dashboard auth fixes (#90)

This commit is contained in:
Erik Vroon
2023-01-18 07:10:49 -08:00
committed by GitHub
parent 3df7e65f19
commit 36f86e4e9b
5 changed files with 53 additions and 16 deletions

View File

@@ -25,6 +25,10 @@ class ClubsResponse(DataResponse[list[Club]]):
pass
class TournamentResponse(DataResponse[Tournament]):
pass
class TournamentsResponse(DataResponse[list[Tournament]]):
pass

View File

@@ -10,20 +10,46 @@ from bracket.models.db.tournament import (
TournamentUpdateBody,
)
from bracket.models.db.user import UserPublic
from bracket.routes.auth import user_authenticated, user_authenticated_for_tournament
from bracket.routes.models import SuccessResponse, TournamentsResponse
from bracket.routes.auth import (
user_authenticated,
user_authenticated_for_tournament,
user_authenticated_or_public_dashboard,
)
from bracket.routes.models import SuccessResponse, TournamentResponse, TournamentsResponse
from bracket.schema import tournaments
from bracket.utils.db import fetch_all_parsed
from bracket.utils.sql import get_user_access_to_club
from bracket.utils.db import fetch_all_parsed, fetch_one_parsed, fetch_one_parsed_certain
from bracket.utils.sql import get_user_access_to_club, get_which_clubs_has_user_access_to
from bracket.utils.types import assert_some
router = APIRouter()
@router.get("/tournaments/{tournament_id}", response_model=TournamentResponse)
async def get_tournament(
tournament_id: int, user: UserPublic | None = Depends(user_authenticated_or_public_dashboard)
) -> TournamentResponse:
tournament = await fetch_one_parsed_certain(
database, Tournament, tournaments.select().where(tournaments.c.id == tournament_id)
)
if user is None and not tournament.dashboard_public:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="You don't have access to this tournament",
headers={"WWW-Authenticate": "Bearer"},
)
return TournamentResponse(data=tournament)
@router.get("/tournaments", response_model=TournamentsResponse)
async def get_tournaments(_: UserPublic = Depends(user_authenticated)) -> TournamentsResponse:
async def get_tournaments(user: UserPublic = Depends(user_authenticated)) -> TournamentsResponse:
user_clubs = await get_which_clubs_has_user_access_to(assert_some(user.id))
return TournamentsResponse(
data=await fetch_all_parsed(database, Tournament, tournaments.select())
data=await fetch_all_parsed(
database,
Tournament,
tournaments.select().where(tournaments.c.club_id.in_(tuple(user_clubs))),
)
)

View File

@@ -87,11 +87,15 @@ async def get_user_access_to_tournament(tournament_id: int, user_id: int) -> boo
return tournament_id in {tournament.id for tournament in result} # type: ignore[attr-defined]
async def get_user_access_to_club(club_id: int, user_id: int) -> bool:
async def get_which_clubs_has_user_access_to(user_id: int) -> set[int]:
query = f'''
SELECT club_id
FROM users_x_clubs
WHERE user_id = :user_id
'''
result = await database.fetch_all(query=query, values={'user_id': user_id})
return club_id in {club.club_id for club in result} # type: ignore[attr-defined]
return {club.club_id for club in result} # type: ignore[attr-defined]
async def get_user_access_to_club(club_id: int, user_id: int) -> bool:
return club_id in await get_which_clubs_has_user_access_to(user_id)

View File

@@ -6,7 +6,7 @@ import NotFoundTitle from '../../404';
import Brackets from '../../../components/brackets/brackets';
import { getTournamentIdFromRouter } from '../../../components/utils/util';
import { Tournament } from '../../../interfaces/tournament';
import { getBaseApiUrl, getRounds, getTournaments } from '../../../services/adapter';
import { getBaseApiUrl, getRounds, getTournament } from '../../../services/adapter';
function TournamentLogo({ tournamentDataFull }: { tournamentDataFull: Tournament }) {
return tournamentDataFull.logo_path ? (
@@ -17,13 +17,10 @@ function TournamentLogo({ tournamentDataFull }: { tournamentDataFull: Tournament
export default function Dashboard() {
const { tournamentData } = getTournamentIdFromRouter();
const swrRoundsResponse: SWRResponse = getRounds(tournamentData.id, true);
const swrTournamentsResponse = getTournaments();
const swrTournamentsResponse = getTournament(tournamentData.id);
const tournaments: Tournament[] =
swrTournamentsResponse.data != null ? swrTournamentsResponse.data.data : [];
const tournamentDataFull = tournaments.filter(
(tournament) => tournament.id === tournamentData.id
)[0];
const tournamentDataFull: Tournament =
swrTournamentsResponse.data != null ? swrTournamentsResponse.data.data : null;
if (tournamentDataFull == null) {
return <NotFoundTitle />;

View File

@@ -52,6 +52,10 @@ export function getClubs(): SWRResponse {
return useSWR('clubs', fetcher);
}
export function getTournament(tournament_id: number): SWRResponse {
return useSWR(`tournaments/${tournament_id}`, fetcher);
}
export function getTournaments(): SWRResponse {
return useSWR('tournaments', fetcher);
}
@@ -65,7 +69,9 @@ export function getTeams(tournament_id: number): SWRResponse {
}
export function getRounds(tournament_id: number, no_draft_rounds: boolean = false): SWRResponse {
return useSWR(`tournaments/${tournament_id}/rounds?no_draft_rounds=${no_draft_rounds}`, fetcher);
return useSWR(`tournaments/${tournament_id}/rounds?no_draft_rounds=${no_draft_rounds}`, fetcher, {
refreshInterval: 3000,
});
}
export function getUpcomingMatches(tournament_id: number): SWRResponse {