Sarting auth implementation in front
This commit is contained in:
@@ -4,7 +4,7 @@ import uuid
|
|||||||
from beanie import PydanticObjectId
|
from beanie import PydanticObjectId
|
||||||
from fastapi import Depends
|
from fastapi import Depends
|
||||||
from fastapi_users import UUIDIDMixin, BaseUserManager, FastAPIUsers, schemas
|
from fastapi_users import UUIDIDMixin, BaseUserManager, FastAPIUsers, schemas
|
||||||
from fastapi_users.authentication import AuthenticationBackend, BearerTransport
|
from fastapi_users.authentication import AuthenticationBackend, BearerTransport, CookieTransport
|
||||||
from fastapi_users.authentication.strategy import AccessTokenDatabase, DatabaseStrategy
|
from fastapi_users.authentication.strategy import AccessTokenDatabase, DatabaseStrategy
|
||||||
from fastapi_users_db_beanie.access_token import BeanieBaseAccessTokenDocument, BeanieAccessTokenDatabase
|
from fastapi_users_db_beanie.access_token import BeanieBaseAccessTokenDocument, BeanieAccessTokenDatabase
|
||||||
from httpx_oauth.clients.google import GoogleOAuth2
|
from httpx_oauth.clients.google import GoogleOAuth2
|
||||||
@@ -19,7 +19,8 @@ discord_oauth_client = DiscordOAuth2(os.getenv("DISCORD_CLIENT_ID"), os.getenv("
|
|||||||
|
|
||||||
TOKEN_LIFETIME = 3600
|
TOKEN_LIFETIME = 3600
|
||||||
|
|
||||||
bearer_transport = BearerTransport(tokenUrl="auth/login")
|
# bearer_transport = BearerTransport(tokenUrl="auth/login")
|
||||||
|
cookie_transport = CookieTransport(cookie_name="rpkapiusersauth")
|
||||||
|
|
||||||
|
|
||||||
class AccessToken(BeanieBaseAccessTokenDocument):
|
class AccessToken(BeanieBaseAccessTokenDocument):
|
||||||
@@ -44,10 +45,7 @@ async def get_user_manager(user_db=Depends(get_user_db)):
|
|||||||
yield UserManager(user_db)
|
yield UserManager(user_db)
|
||||||
|
|
||||||
|
|
||||||
auth_backend = AuthenticationBackend(
|
auth_backend = AuthenticationBackend(name="db", transport=cookie_transport, get_strategy=get_database_strategy,
|
||||||
name="db",
|
|
||||||
transport=bearer_transport,
|
|
||||||
get_strategy=get_database_strategy,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fastapi_users = FastAPIUsers[User, PydanticObjectId](get_user_manager, [auth_backend])
|
fastapi_users = FastAPIUsers[User, PydanticObjectId](get_user_manager, [auth_backend])
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ services:
|
|||||||
api:
|
api:
|
||||||
build:
|
build:
|
||||||
context: ./api
|
context: ./api
|
||||||
#image: roleplay-contracts-api-dev
|
image: roleplay-contracts-api-dev
|
||||||
env_file: "./.env"
|
env_file: "./.env"
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
@@ -16,21 +16,21 @@ services:
|
|||||||
- "traefik.http.routers.back.rule=PathPrefix(`/api/v1/`)"
|
- "traefik.http.routers.back.rule=PathPrefix(`/api/v1/`)"
|
||||||
- "traefik.http.services.back.loadbalancer.server.port=8000"
|
- "traefik.http.services.back.loadbalancer.server.port=8000"
|
||||||
|
|
||||||
# gui:
|
gui:
|
||||||
# build:
|
build:
|
||||||
# context: ./gui
|
context: ./gui
|
||||||
# image: roleplay-contracts-gui-dev
|
image: roleplay-contracts-gui-dev
|
||||||
# restart: always
|
restart: always
|
||||||
# ports:
|
ports:
|
||||||
# - "4200:4200"
|
- "4200:4200"
|
||||||
# volumes:
|
volumes:
|
||||||
# - ./gui/rpk-gui/src:/app/src
|
- ./gui/rpk-gui/src:/app/src
|
||||||
# - ./gui/rpk-gui/public:/app/public
|
- ./gui/rpk-gui/public:/app/public
|
||||||
# labels:
|
labels:
|
||||||
# - "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
# - "traefik.http.routers.front.entrypoints=web"
|
- "traefik.http.routers.front.entrypoints=web"
|
||||||
# - "traefik.http.routers.front.rule=PathPrefix(`/`)"
|
- "traefik.http.routers.front.rule=PathPrefix(`/`)"
|
||||||
# - "traefik.http.services.front.loadbalancer.server.port=4200"
|
- "traefik.http.services.front.loadbalancer.server.port=4200"
|
||||||
|
|
||||||
proxy:
|
proxy:
|
||||||
image: traefik:latest
|
image: traefik:latest
|
||||||
|
|||||||
13
gui/Dockerfile
Normal file
13
gui/Dockerfile
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
FROM node:lts-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
RUN npm install -g @angular/cli http-server
|
||||||
|
COPY rpk-gui/package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
COPY rpk-gui/ .
|
||||||
|
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
EXPOSE 4200
|
||||||
|
|
||||||
|
CMD [ "npm", "run", "ng", "serve", "--", "--host", "0.0.0.0", "--disable-host-check" ]
|
||||||
18
gui/rpk-gui/package-lock.json
generated
18
gui/rpk-gui/package-lock.json
generated
@@ -17,8 +17,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.21.0",
|
"@eslint/js": "^9.21.0",
|
||||||
"@types/react": "^19.0.10",
|
"@types/react": "^19.1.0",
|
||||||
"@types/react-dom": "^19.0.4",
|
"@types/react-dom": "^19.1.1",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
"eslint": "^9.21.0",
|
"eslint": "^9.21.0",
|
||||||
"eslint-plugin-react-hooks": "^5.1.0",
|
"eslint-plugin-react-hooks": "^5.1.0",
|
||||||
@@ -2066,20 +2066,18 @@
|
|||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/react": {
|
"node_modules/@types/react": {
|
||||||
"version": "19.0.12",
|
"version": "19.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.12.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.0.tgz",
|
||||||
"integrity": "sha512-V6Ar115dBDrjbtXSrS+/Oruobc+qVbbUxDFC1RSbRqLt5SYvxxyIDrSC85RWml54g+jfNeEMZhEj7wW07ONQhA==",
|
"integrity": "sha512-UaicktuQI+9UKyA4njtDOGBD/67t8YEBt2xdfqu8+gP9hqPUPsiXlNPcpS2gVdjmis5GKPG3fCxbQLVgxsQZ8w==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/react-dom": {
|
"node_modules/@types/react-dom": {
|
||||||
"version": "19.0.4",
|
"version": "19.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.1.tgz",
|
||||||
"integrity": "sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==",
|
"integrity": "sha512-jFf/woGTVTjUJsl2O7hcopJ1r0upqoq/vIOoCj0yLh3RIXxWcljlpuZ+vEBRXsymD1jhfeJrlyTy/S1UW+4y1w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "^19.0.0"
|
"@types/react": "^19.0.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,13 +15,12 @@
|
|||||||
"better-auth": "^1.2.5",
|
"better-auth": "^1.2.5",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-router": "^7.4.1",
|
"react-router": "^7.4.1"
|
||||||
"react-router-auth"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.21.0",
|
"@eslint/js": "^9.21.0",
|
||||||
"@types/react": "^19.0.10",
|
"@types/react": "^19.1.0",
|
||||||
"@types/react-dom": "^19.0.4",
|
"@types/react-dom": "^19.1.1",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
"eslint": "^9.21.0",
|
"eslint": "^9.21.0",
|
||||||
"eslint-plugin-react-hooks": "^5.1.0",
|
"eslint-plugin-react-hooks": "^5.1.0",
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
|
//https://www.robinwieruch.de/react-router-private-routes/
|
||||||
|
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import reactLogo from './assets/react.svg'
|
import reactLogo from './assets/react.svg'
|
||||||
import viteLogo from '/vite.svg'
|
import viteLogo from '/vite.svg'
|
||||||
import './App.css'
|
import './App.css'
|
||||||
|
|
||||||
import {createBrowserRouter, Link, RouterProvider} from "react-router";
|
import {createBrowserRouter, Link, Route, RouterProvider, Routes} from "react-router";
|
||||||
import { EntityList } from "./page/entities/list.tsx";
|
import { EntityList } from "./pages/entities/List.tsx";
|
||||||
|
import {ProtectedRoute} from "./pages/auth/ProtectedRoute.tsx";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
const [user, setUser] = useState<AuthUser | null>(null)
|
||||||
const [count, setCount] = useState(0)
|
const [count, setCount] = useState(0)
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
@@ -23,8 +27,13 @@ function App() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<RouterProvider router={router}>
|
<RouterProvider router={router}>
|
||||||
|
|
||||||
</RouterProvider>
|
</RouterProvider>
|
||||||
|
<Routes>
|
||||||
|
<Route index element={ <h1>INDEX</h1> } />
|
||||||
|
<Route element={ <ProtectedRoute user={user} /> }>
|
||||||
|
<Route path="toto" element={ <h1>PROTECTED ROUTE</h1>} />
|
||||||
|
</Route>
|
||||||
|
</Routes>
|
||||||
<div>
|
<div>
|
||||||
<a href="https://vite.dev" target="_blank">
|
<a href="https://vite.dev" target="_blank">
|
||||||
<img src={viteLogo} className="logo" alt="Vite logo" />
|
<img src={viteLogo} className="logo" alt="Vite logo" />
|
||||||
|
|||||||
14
gui/rpk-gui/src/pages/auth/Login.tsx
Normal file
14
gui/rpk-gui/src/pages/auth/Login.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
export const Login = () => {
|
||||||
|
async function handleLogin(e: any) {
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={ handleLogin }>
|
||||||
|
<input type={ "text" } name={ "email" } />
|
||||||
|
<input type={ "password" } name={ "password" } />
|
||||||
|
<input type={ "submit" } />
|
||||||
|
</form>
|
||||||
|
)
|
||||||
|
}
|
||||||
16
gui/rpk-gui/src/pages/auth/ProtectedRoute.tsx
Normal file
16
gui/rpk-gui/src/pages/auth/ProtectedRoute.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import {Navigate, Outlet} from "react-router";
|
||||||
|
|
||||||
|
type AuthUser = { id: string; name: string };
|
||||||
|
|
||||||
|
type ProtectedRouteProps = {
|
||||||
|
user: AuthUser | null;
|
||||||
|
redirectPath?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ProtectedRoute = ({ user, redirectPath = "/" }: ProtectedRouteProps) => {
|
||||||
|
if (!user) {
|
||||||
|
return <Navigate to={redirectPath} replace />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Outlet />;
|
||||||
|
};
|
||||||
15
gui/rpk-gui/src/pages/auth/Register.tsx
Normal file
15
gui/rpk-gui/src/pages/auth/Register.tsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
export const Register = () => {
|
||||||
|
async function handleRegister(e: any) {
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={ handleRegister }>
|
||||||
|
<input type={ "text" } name={ "email" } />
|
||||||
|
<input type={ "password" } name={ "password" }/>
|
||||||
|
<input type={ "password" } name={ "confirm_password" }/>
|
||||||
|
<input type={ "submit" } />
|
||||||
|
</form>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
export const EntityList = (props: any) => {
|
export const EntityList = () => {
|
||||||
return (
|
return (
|
||||||
<h1>List des entity: Yoyoyo</h1>
|
<h1>List des entity: Yoyoyo</h1>
|
||||||
)
|
)
|
||||||
Reference in New Issue
Block a user