clientid works

This commit is contained in:
2024-04-14 20:28:21 +03:00
parent af608f5b26
commit ffe45a821d
10 changed files with 140 additions and 10 deletions

View File

@ -63,8 +63,15 @@ async def register(
return user return user
@router.get("/me", response_model=schemas.User) @router.get("/me")
async def read_users_me( async def read_users_me(
current_user: Annotated[schemas.User, Depends(services.get_current_active_user)], current_user: Annotated[schemas.User, Depends(services.get_current_active_user)],
): ) -> schemas.User:
return current_user return current_user
@router.get("/anon")
async def get_qnon_user(
anon_user: Annotated[schemas.AnonUser, Depends(services.get_anon_user)]
) -> schemas.AnonUser:
return anon_user

View File

@ -27,3 +27,11 @@ class Token(BaseModel):
class TokenData(BaseModel): class TokenData(BaseModel):
username: Union[str, None] = None username: Union[str, None] = None
class AnonUser(BaseModel):
id: UUID
name: Union[str, None] = None
class Config:
from_attributes = True

View File

@ -1,4 +1,4 @@
from fastapi import status, HTTPException, Depends from fastapi import status, HTTPException, Depends, Header
from fastapi.security import OAuth2PasswordBearer from fastapi.security import OAuth2PasswordBearer
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from jose import JWTError, jwt from jose import JWTError, jwt
@ -65,7 +65,7 @@ def create_user(db: Session, user_data: schemas.UserRegister) -> schemas.UserInD
return schemas.UserInDB.model_validate(user) return schemas.UserInDB.model_validate(user)
async def get_current_user( def get_current_user(
token: Annotated[str, Depends(oauth2_scheme)], token: Annotated[str, Depends(oauth2_scheme)],
db: Annotated[Session, Depends(get_db)], db: Annotated[Session, Depends(get_db)],
) -> schemas.UserInDB: ) -> schemas.UserInDB:
@ -90,7 +90,7 @@ async def get_current_user(
return user return user
async def get_current_user_or_none( def get_current_user_or_none(
token: Annotated[str, Depends(oauth2_scheme)], token: Annotated[str, Depends(oauth2_scheme)],
db: Annotated[Session, Depends(get_db)], db: Annotated[Session, Depends(get_db)],
) -> Union[schemas.UserInDB, None]: ) -> Union[schemas.UserInDB, None]:
@ -108,9 +108,36 @@ async def get_current_user_or_none(
return user return user
async def get_current_active_user( def get_current_active_user(
current_user: Annotated[schemas.User, Depends(get_current_user)], current_user: Annotated[schemas.User, Depends(get_current_user)],
): ):
if not current_user.is_active: if not current_user.is_active:
raise HTTPException(status_code=400, detail="Inactive user") raise HTTPException(status_code=400, detail="Inactive user")
return current_user return current_user
def create_anon_user(db: Annotated[Session, Depends(get_db)]) -> schemas.AnonUser:
u = models.AnonymousUser()
db.add(u)
db.commit()
# return schemas.AnonUser.model_validate(u)
return u
def get_anon_user(
db: Annotated[Session, Depends(get_db)],
x_client_id: Annotated[Union[str, None], Header()] = None,
) -> schemas.AnonUser:
if x_client_id:
anon = (
db.query(models.AnonymousUser)
.filter(models.AnonymousUser.id == x_client_id)
.first()
)
if anon:
return anon
raise HTTPException(
status_code=status.HTTP_418_IM_A_TEAPOT,
detail={"message": "tf dude? trying to spoof your client id?"},
)
return create_anon_user(db)

View File

@ -46,3 +46,10 @@ async def create_queue(
db: Annotated[Session, Depends(get_db)], db: Annotated[Session, Depends(get_db)],
) -> schemas.QueueInDb: ) -> schemas.QueueInDb:
return services.create_queue(new_queue=new_queue, current_user=current_user, db=db) return services.create_queue(new_queue=new_queue, current_user=current_user, db=db)
@router.post("/{queue_id}/join")
async def join_queue(
queue_user: Annotated[schemas.QueueUser, Depends(services.join_queue)]
) -> schemas.QueueUser:
return queue_user

View File

@ -30,3 +30,12 @@ class QueueInDb(Queue):
class QueueDetail(Queue): class QueueDetail(Queue):
id: UUID id: UUID
participants: ParticipantInfo participants: ParticipantInfo
class QueueUser(BaseModel):
id: UUID
position: int
passed: bool
class Config:
from_attributes = True

View File

@ -12,6 +12,11 @@ from ..auth import schemas as auth_schemas
from . import schemas from . import schemas
def get_queue_by_id(queue_id: UUID, db: Session) -> models.Queue:
q = db.query(models.Queue).filter(models.Queue.id == queue_id).first()
return q
def get_user_queues( def get_user_queues(
current_user: Annotated[auth_schemas.User, Depends(auth_services.get_current_user)] current_user: Annotated[auth_schemas.User, Depends(auth_services.get_current_user)]
) -> list[schemas.QueueInDb]: ) -> list[schemas.QueueInDb]:
@ -51,3 +56,29 @@ def get_detailed_queue(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail="Not Found", detail="Not Found",
) )
def join_queue(
queue_id: UUID,
client: Annotated[auth_schemas.AnonUser, Depends(auth_services.get_anon_user)],
db: Annotated[Session, Depends(get_db)],
) -> schemas.QueueUser:
q = get_queue_by_id(queue_id, db)
if q:
if not q.users.filter(models.QueueUser.user_id == client.id).first():
last_qu = q.users.order_by(models.QueueUser.position.desc()).first()
position = last_qu.position + 1 if last_qu else 0
new_qu = models.QueueUser(
user_id=client.id, queue_id=q.id, position=position
)
db.add(new_qu)
db.commit()
return new_qu
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail="Already joined",
)
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Not Found",
)

View File

@ -7,12 +7,13 @@ import {
import React, { useContext, useEffect, useRef, useState } from "react"; import React, { useContext, useEffect, useRef, useState } from "react";
import { import {
TokenResponse, TokenResponse,
useGetClientQuery,
useGetUserQuery, useGetUserQuery,
useLoginMutation, useLoginMutation,
useRegisterMutation, useRegisterMutation,
} from "../slice/AuthApi"; } from "../slice/AuthApi";
import { MessageContext } from "../App"; import { MessageContext } from "../App";
import { store, updateToken, updateUser } from "../config/store"; import { store, updateClient, updateToken, updateUser } from "../config/store";
import tr from "../config/translation"; import tr from "../config/translation";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
@ -35,6 +36,15 @@ const AuthModal = (props: {
} }
}, [data, isFetching, useGetUserQuery]); }, [data, isFetching, useGetUserQuery]);
const { data: clientData, isFetching: isFetchingClient } = useGetClientQuery(
{}
);
useEffect(() => {
if (!isFetchingClient) {
store.dispatch(updateClient(clientData.id));
}
}, [clientData, isFetchingClient, useGetClientQuery]);
const [current, setCurrent] = useState("login"); const [current, setCurrent] = useState("login");
useEffect(() => { useEffect(() => {
if (carousel?.current !== undefined) { if (carousel?.current !== undefined) {

View File

@ -11,11 +11,13 @@ import { NewsApi } from "../slice/NewsApi";
export type AuthDataType = { export type AuthDataType = {
token: string | null; token: string | null;
clientId: string | null;
user: { name: string | null; username: string } | null; user: { name: string | null; username: string } | null;
}; };
const initialAuthDataState: AuthDataType = { const initialAuthDataState: AuthDataType = {
token: null, token: null,
clientId: null,
user: null, user: null,
}; };
@ -35,6 +37,8 @@ export type StorePrototype = {
export const updateToken = createAction<string>("auth/updateToken"); export const updateToken = createAction<string>("auth/updateToken");
export const getLocalToken = createAction("auth/getLocalToken"); export const getLocalToken = createAction("auth/getLocalToken");
export const updateClient = createAction<string>("auth/updateClient");
export const getLocalClient = createAction("auth/getLocalClient");
export const updateUser = createAction<User>("auth/updateUser"); export const updateUser = createAction<User>("auth/updateUser");
export const logOut = createAction("auth/logOut"); export const logOut = createAction("auth/logOut");
@ -58,6 +62,16 @@ export const store = configureStore({
state.token = token; state.token = token;
} }
}); });
builder.addCase(updateClient, (state, action) => {
state.clientId = action.payload;
localStorage.setItem("clientId", action.payload);
});
builder.addCase(getLocalClient, (state) => {
const clientId: string | null = localStorage.getItem("clientId");
if (clientId) {
state.clientId = clientId;
}
});
builder.addCase(updateUser, (state, action) => { builder.addCase(updateUser, (state, action) => {
state.user = action.payload; state.user = action.payload;
}); });

View File

@ -1,7 +1,12 @@
import React, { ReactNode } from "react"; import React, { ReactNode } from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom"; import { BrowserRouter, Route, Routes } from "react-router-dom";
import MainPage from "./MainPage"; import MainPage from "./MainPage";
import { getLocalToken, loadLanguage, store } from "../config/store"; import {
getLocalClient,
getLocalToken,
loadLanguage,
store,
} from "../config/store";
import DashboardPage from "./DashboardPage"; import DashboardPage from "./DashboardPage";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import NotFoundPage from "./NotFoundPage"; import NotFoundPage from "./NotFoundPage";
@ -12,6 +17,7 @@ import QueueCard from "../components/queue/QueueCard";
const AppRoutes = ({ children }: { children: ReactNode }) => { const AppRoutes = ({ children }: { children: ReactNode }) => {
store.dispatch(getLocalToken()); store.dispatch(getLocalToken());
store.dispatch(getLocalClient());
store.dispatch(loadLanguage()); store.dispatch(loadLanguage());
return ( return (

View File

@ -34,6 +34,10 @@ export const AuthApi = createApi({
if (token) { if (token) {
headers.set("authorization", `Bearer ${token}`); headers.set("authorization", `Bearer ${token}`);
} }
const clientID = (getState() as RootState).auth.clientId;
if (clientID) {
headers.set("X-Client-Id", clientID);
}
return headers; return headers;
}, },
}), }),
@ -41,6 +45,9 @@ export const AuthApi = createApi({
getUser: builder.query({ getUser: builder.query({
query: () => "/me", query: () => "/me",
}), }),
getClient: builder.query({
query: () => "/anon",
}),
login: builder.mutation({ login: builder.mutation({
query: (data: FormData) => ({ query: (data: FormData) => ({
url: "/token", url: "/token",
@ -59,5 +66,9 @@ export const AuthApi = createApi({
}), }),
}); });
export const { useGetUserQuery, useLoginMutation, useRegisterMutation } = export const {
AuthApi; useGetUserQuery,
useGetClientQuery,
useLoginMutation,
useRegisterMutation,
} = AuthApi;