diff --git a/main.py b/main.py index 4fee76b..7ce4c5a 100644 --- a/main.py +++ b/main.py @@ -59,7 +59,7 @@ def add_players(players: list[Player]): session.commit() -def list_players(): +async def list_players(): with Session(engine) as session: statement = select(Player).order_by(Player.display_name) players = session.exec(statement).fetchall() @@ -69,6 +69,11 @@ def list_players(): ] +async def read_teams_me(user: Annotated[Player, Depends(get_current_active_user)]): + with Session(engine) as session: + return [p.teams for p in session.exec(select(P).where(P.id == user.id))][0] + + def list_teams(): with Session(engine) as session: statement = select(Team) @@ -79,12 +84,16 @@ player_router = APIRouter(prefix="/player") player_router.add_api_route("/list", endpoint=list_players, methods=["GET"]) player_router.add_api_route("/add", endpoint=add_player, methods=["POST"]) player_router.add_api_route("/me", endpoint=read_player_me, methods=["GET"]) +player_router.add_api_route("/me/teams", endpoint=read_teams_me, methods=["GET"]) player_router.add_api_route("/me/items", endpoint=read_own_items, methods=["GET"]) player_router.add_api_route( "/change_password", endpoint=change_password, methods=["POST"] ) -team_router = APIRouter(prefix="/team") +team_router = APIRouter( + prefix="/team", + dependencies=[Security(get_current_active_user, scopes=["admin"])], +) team_router.add_api_route("/list", endpoint=list_teams, methods=["GET"]) team_router.add_api_route("/add", endpoint=add_team, methods=["POST"]) diff --git a/security.py b/security.py index aa574bd..5ad8bb7 100644 --- a/security.py +++ b/security.py @@ -60,6 +60,7 @@ oauth2_scheme = CookieOAuth2( tokenUrl="api/token", scopes={ "analysis": "Access the results.", + "admin": "Maintain DB etc.", }, ) diff --git a/src/App.css b/src/App.css index f65621f..435b940 100644 --- a/src/App.css +++ b/src/App.css @@ -421,7 +421,7 @@ button { .user-info { display: grid; - grid-template-columns: 1fr 1fr; + grid-template-columns: 8em 12em; gap: 2px 16px; div { diff --git a/src/Avatar.tsx b/src/Avatar.tsx index f1d53a1..58d9488 100644 --- a/src/Avatar.tsx +++ b/src/Avatar.tsx @@ -4,13 +4,14 @@ import { User } from "./api"; import { useTheme } from "./ThemeProvider"; import { colourTheme, darkTheme, normalTheme, rainbowTheme } from "./themes"; import { useNavigate } from "react-router"; +import { Team } from "./types"; interface ContextMenuItem { label: string; onClick: () => void; } -const UserInfo = (user: User) => { +const UserInfo = (user: User, teams: Team[] | undefined) => { return (
@@ -24,17 +25,38 @@ const UserInfo = (user: User) => {
number:
-
{user?.number ? user?.number : "-"}
+
{user?.number || "-"}
email:
-
{user?.email ? user?.email : "-"}
+
{user?.email || "-"}
+ {teams && ( + <> +
+ teams: +
+ + + )}
); }; export default function Avatar() { - const { user, onLogout } = useSession(); + const { user, teams, onLogout } = useSession(); const { theme, setTheme } = useTheme(); const navigate = useNavigate(); const [contextMenu, setContextMenu] = useState<{ @@ -118,9 +140,9 @@ export default function Avatar() { const dialogRef = createRef(); function handleViewProfile() { - if (user) { + if (user && teams) { dialogRef.current?.showModal(); - setDialog(UserInfo(user)); + setDialog(UserInfo(user, teams)); } } diff --git a/src/Session.tsx b/src/Session.tsx index fa0987a..457212d 100644 --- a/src/Session.tsx +++ b/src/Session.tsx @@ -5,9 +5,10 @@ import { useEffect, useState, } from "react"; -import { currentUser, logout, User } from "./api"; +import { apiAuth, currentUser, logout, User } from "./api"; import { Login } from "./Login"; import Header from "./Header"; +import { Team } from "./types"; export interface SessionProviderProps { children: ReactNode; @@ -15,11 +16,13 @@ export interface SessionProviderProps { export interface Session { user: User | null; + teams: Team[] | null; onLogout: () => void; } const sessionContext = createContext({ user: null, + teams: null, onLogout: () => {}, }); @@ -27,6 +30,7 @@ export function SessionProvider(props: SessionProviderProps) { const { children } = props; const [user, setUser] = useState(null); + const [teams, setTeams] = useState(); const [err, setErr] = useState(null); const [loading, setLoading] = useState(false); @@ -44,8 +48,14 @@ export function SessionProvider(props: SessionProviderProps) { .finally(() => setLoading(false)); } + async function loadTeam() { + const teams: Team[] = await apiAuth("player/me/teams", null, "GET"); + if (teams) setTeams(teams); + } + useEffect(() => { loadUser(); + setTimeout(() => loadTeam(), 1500); }, []); function onLogin(user: User) { @@ -77,7 +87,7 @@ export function SessionProvider(props: SessionProviderProps) { content = ; } else content = ( - + {children} ); diff --git a/src/api.ts b/src/api.ts index 6074927..94588c2 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,4 +1,5 @@ import { useSession } from "./Session"; +import { Team } from "./types"; export const baseUrl = import.meta.env.VITE_BASE_URL as string; diff --git a/src/types.ts b/src/types.ts index a0951c9..5633dd4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -32,3 +32,9 @@ export interface MVPRanking { user: number; mvps: number[]; } + +export interface Team { + name: string; + location: string; + country: string; +}