commit
52afe12a01
@ -13,7 +13,7 @@ import org.eclipse.microprofile.config.inject.ConfigProperty;
|
|||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
@Path("/auth")
|
@Path("api/auth")
|
||||||
public class AuthEndpoints {
|
public class AuthEndpoints {
|
||||||
|
|
||||||
@ConfigProperty(name = "login_redirect")
|
@ConfigProperty(name = "login_redirect")
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import jakarta.ws.rs.core.MediaType;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Path("/club")
|
@Path("api/club")
|
||||||
public class ClubEndpoints {
|
public class ClubEndpoints {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
|||||||
@ -26,7 +26,7 @@ import java.util.List;
|
|||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
@Path("/member")
|
@Path("api/member")
|
||||||
public class CombEndpoints {
|
public class CombEndpoints {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
|||||||
@ -21,15 +21,29 @@ quarkus.oidc.auth-server-url=https://auth.safca.fr/auth/realms/safca
|
|||||||
quarkus.oidc.client-id=backend
|
quarkus.oidc.client-id=backend
|
||||||
quarkus.oidc.credentials.secret=secret
|
quarkus.oidc.credentials.secret=secret
|
||||||
quarkus.oidc.tls.verification=required
|
quarkus.oidc.tls.verification=required
|
||||||
#quarkus.oidc.tls.verification=none
|
quarkus.oidc.application-type=web-app
|
||||||
|
quarkus.oidc.roles.source=accesstoken
|
||||||
|
|
||||||
quarkus.http.limits.max-body-size=10M
|
quarkus.http.limits.max-body-size=10M
|
||||||
|
|
||||||
quarkus.oidc.token-state-manager.split-tokens=true
|
|
||||||
|
|
||||||
database.prefix = test2_
|
database.prefix = test2_
|
||||||
database.database=ffsaf
|
database.database=ffsaf
|
||||||
database.hostname=localhost
|
database.hostname=localhost
|
||||||
database.port=3306
|
database.port=3306
|
||||||
database.user=root
|
database.user=root
|
||||||
database.pass=
|
database.pass=
|
||||||
|
|
||||||
|
#Login
|
||||||
|
quarkus.oidc.token-state-manager.split-tokens=true
|
||||||
|
|
||||||
|
quarkus.oidc.authentication.redirect-path=/api/auth/login
|
||||||
|
quarkus.oidc.logout.path=/api/logout
|
||||||
|
quarkus.oidc.logout.post-logout-path=/index.html
|
||||||
|
|
||||||
|
# Only the authenticated users can initiate a logout:
|
||||||
|
quarkus.http.auth.permission.authenticated.paths=api/logout,api/auth/login
|
||||||
|
quarkus.http.auth.permission.authenticated.policy=authenticated
|
||||||
|
|
||||||
|
# All users can see the welcome page:
|
||||||
|
quarkus.http.auth.permission.public.paths=/index.html
|
||||||
|
quarkus.http.auth.permission.public.policy=permit
|
||||||
@ -7,7 +7,6 @@ import {AdminRoot, getAdminChildren} from "./pages/admin/AdminRoot.jsx";
|
|||||||
import {AuthCallback} from "./components/auhCallback.jsx";
|
import {AuthCallback} from "./components/auhCallback.jsx";
|
||||||
import {KeycloakContextProvider, useAuthDispatch} from "./hooks/useAuth.jsx";
|
import {KeycloakContextProvider, useAuthDispatch} from "./hooks/useAuth.jsx";
|
||||||
import {check_validity} from "./utils/auth.js";
|
import {check_validity} from "./utils/auth.js";
|
||||||
import {MemberList} from "./pages/admin/MemberList.jsx";
|
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
|
|||||||
@ -2,8 +2,6 @@ import {LoadingContextProvider, useLoadingSwitcher} from "../hooks/useLoading.js
|
|||||||
import {useFetch} from "../hooks/useFetch.js";
|
import {useFetch} from "../hooks/useFetch.js";
|
||||||
import {AxiosError} from "./AxiosError.jsx";
|
import {AxiosError} from "./AxiosError.jsx";
|
||||||
|
|
||||||
const api_url = import.meta.env.VITE_API_URL;
|
|
||||||
|
|
||||||
export function ClubSelect({defaultValue, name}) {
|
export function ClubSelect({defaultValue, name}) {
|
||||||
return <LoadingContextProvider>
|
return <LoadingContextProvider>
|
||||||
<div className="input-group mb-3">
|
<div className="input-group mb-3">
|
||||||
@ -14,7 +12,7 @@ export function ClubSelect({defaultValue, name}) {
|
|||||||
|
|
||||||
function ClubSelect_({defaultValue, name}) {
|
function ClubSelect_({defaultValue, name}) {
|
||||||
const setLoading = useLoadingSwitcher()
|
const setLoading = useLoadingSwitcher()
|
||||||
const {data, error} = useFetch(`${api_url}/club/no_detail`, setLoading, 1)
|
const {data, error} = useFetch(`/club/no_detail`, setLoading, 1)
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
{data
|
{data
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
import LogoIcon from '../assets/FFSSAF-bord-blanc-fond-transparent.webp'
|
import LogoIcon from '../assets/FFSSAF-bord-blanc-fond-transparent.webp'
|
||||||
import './Nav.css'
|
import './Nav.css'
|
||||||
import {NavLink} from "react-router-dom";
|
import {NavLink} from "react-router-dom";
|
||||||
import {useAuth, useAuthDispatch} from "../hooks/useAuth.jsx";
|
import {useAuth} from "../hooks/useAuth.jsx";
|
||||||
import {login, logout} from "../utils/auth.js";
|
import {login, logout} from "../utils/auth.js";
|
||||||
|
|
||||||
|
|
||||||
export function Nav() {
|
export function Nav() {
|
||||||
|
|
||||||
return <nav className="navbar navbar-light navbar-expand-md bg-body-tertiary " id="main-navbar">
|
return <nav className="navbar navbar-light navbar-expand-md bg-body-tertiary " id="main-navbar">
|
||||||
@ -50,16 +49,13 @@ function AdminMenu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function LoginMenu() {
|
function LoginMenu() {
|
||||||
const {token, refresh, is_authenticated} = useAuth()
|
const {is_authenticated} = useAuth()
|
||||||
const dispatch = useAuthDispatch()
|
|
||||||
|
|
||||||
return <li className="nav-item">
|
return <li className="nav-item">
|
||||||
{!is_authenticated ? (
|
{!is_authenticated ? (
|
||||||
<div className="nav-link" onClick={() => login()}>Connexion</div>
|
<div className="nav-link" onClick={() => login()}>Connexion</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="nav-link" onClick={() => {
|
<div className="nav-link" onClick={() => logout()}>Déconnexion</div>
|
||||||
logout(token, refresh).then(() => dispatch({type: 'invalidate'}))
|
|
||||||
}}>Déconnexion</div>
|
|
||||||
)}
|
)}
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import {useEffect, useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
import axios from "axios";
|
import {apiAxios} from "../utils/Tools.js";
|
||||||
|
|
||||||
function stdAction(promise, setData, setErrors, setLoading = null, loadingLevel = 1) {
|
function stdAction(promise, setData, setErrors, setLoading = null, loadingLevel = 1) {
|
||||||
if (setLoading)
|
if (setLoading)
|
||||||
@ -15,19 +15,12 @@ function stdAction(promise, setData, setErrors, setLoading = null, loadingLevel
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useFetch(url, setLoading = null, loadingLevel = 1, options = {}) {
|
export function useFetch(url, setLoading = null, loadingLevel = 1, config = {}) {
|
||||||
const [data, setData] = useState(null)
|
const [data, setData] = useState(null)
|
||||||
const [error, setErrors] = useState(null)
|
const [error, setErrors] = useState(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
stdAction(axios.get(url, {
|
stdAction(apiAxios.get(url, config), setData, setErrors, setLoading, loadingLevel)
|
||||||
...options,
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Bearer ${localStorage.getItem("access_token")}`,
|
|
||||||
'Accept': 'application/json; charset=UTF-8',
|
|
||||||
...options?.headers
|
|
||||||
}
|
|
||||||
}), setData, setErrors, setLoading, loadingLevel)
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -35,19 +28,12 @@ export function useFetch(url, setLoading = null, loadingLevel = 1, options = {})
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useFetchPut(url, dataRequest, setLoading = null, loadingLevel = 1, options = {}) {
|
export function useFetchPut(url, dataRequest, setLoading = null, loadingLevel = 1, config = {}) {
|
||||||
const [data, setData] = useState(null)
|
const [data, setData] = useState(null)
|
||||||
const [error, setErrors] = useState(null)
|
const [error, setErrors] = useState(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
stdAction(axios.put(url, dataRequest, {
|
stdAction(apiAxios.put(url, dataRequest, config), setData, setErrors, setLoading, loadingLevel)
|
||||||
...options,
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Bearer ${localStorage.getItem("access_token")}`,
|
|
||||||
'Accept': 'application/json; charset=UTF-8',
|
|
||||||
...options?.headers
|
|
||||||
}
|
|
||||||
}), setData, setErrors, setLoading, loadingLevel)
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -6,8 +6,6 @@ import {useState} from "react";
|
|||||||
import {Input} from "../../components/Input.jsx";
|
import {Input} from "../../components/Input.jsx";
|
||||||
import {useNavigate} from "react-router-dom";
|
import {useNavigate} from "react-router-dom";
|
||||||
|
|
||||||
const api_url = import.meta.env.VITE_API_URL;
|
|
||||||
|
|
||||||
const removeDiacritics = str => {
|
const removeDiacritics = str => {
|
||||||
return str
|
return str
|
||||||
.normalize('NFD')
|
.normalize('NFD')
|
||||||
@ -16,7 +14,7 @@ const removeDiacritics = str => {
|
|||||||
|
|
||||||
export function MemberList() {
|
export function MemberList() {
|
||||||
const setLoading = useLoadingSwitcher()
|
const setLoading = useLoadingSwitcher()
|
||||||
const {data, error} = useFetch(`${api_url}/member/all`, setLoading, 1)
|
const {data, error} = useFetch(`/member/all`, setLoading, 1)
|
||||||
const [searchInput, setSearchInput] = useState("");
|
const [searchInput, setSearchInput] = useState("");
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
|||||||
@ -1,21 +1,20 @@
|
|||||||
import {useNavigate, useParams} from "react-router-dom";
|
import {useNavigate, useParams} from "react-router-dom";
|
||||||
import {useLoadingSwitcher} from "../../hooks/useLoading.jsx";
|
import {useLoadingSwitcher} from "../../hooks/useLoading.jsx";
|
||||||
import {useFetch, useFetchPut} from "../../hooks/useFetch.js";
|
import {useFetch} from "../../hooks/useFetch.js";
|
||||||
import {AxiosError} from "../../components/AxiosError.jsx";
|
import {AxiosError} from "../../components/AxiosError.jsx";
|
||||||
import {ClubSelect} from "../../components/ClubSelect.jsx";
|
import {ClubSelect} from "../../components/ClubSelect.jsx";
|
||||||
import {useEffect, useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
import {getCategoryFormBirthDate, getSaison} from "../../utils/Tools.js";
|
import {apiAxios, getCategoryFormBirthDate} from "../../utils/Tools.js";
|
||||||
import axios from "axios";
|
|
||||||
import imageCompression from "browser-image-compression";
|
import imageCompression from "browser-image-compression";
|
||||||
|
|
||||||
const api_url = import.meta.env.VITE_API_URL;
|
const vite_url = import.meta.env.VITE_URL;
|
||||||
|
|
||||||
export function MemberPage() {
|
export function MemberPage() {
|
||||||
const {id} = useParams()
|
const {id} = useParams()
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const setLoading = useLoadingSwitcher()
|
const setLoading = useLoadingSwitcher()
|
||||||
const {data, error} = useFetch(`${api_url}/member/${id}`, setLoading, 1)
|
const {data, error} = useFetch(`/member/${id}`, setLoading, 1)
|
||||||
|
|
||||||
const handleSubmit = (event) => {
|
const handleSubmit = (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -36,9 +35,8 @@ export function MemberPage() {
|
|||||||
formData.append("grade_arbitrage", event.target.grade_arbitrage?.value);
|
formData.append("grade_arbitrage", event.target.grade_arbitrage?.value);
|
||||||
|
|
||||||
const send = (formData_) => {
|
const send = (formData_) => {
|
||||||
axios.post(`${api_url}/member/${id}`, formData_, {
|
apiAxios.post(`/member/${id}`, formData_, {
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${localStorage.getItem("access_token")}`,
|
|
||||||
'Accept': '*/*',
|
'Accept': '*/*',
|
||||||
'Content-Type': 'multipart/form-data',
|
'Content-Type': 'multipart/form-data',
|
||||||
}
|
}
|
||||||
@ -94,7 +92,7 @@ function MemberForm({data, handleSubmit}) {
|
|||||||
<div className="card-body text-center">
|
<div className="card-body text-center">
|
||||||
<div className="input-group mb-3">
|
<div className="input-group mb-3">
|
||||||
<img
|
<img
|
||||||
src={"http://localhost:8080/member/"+data.id+"/photo"}
|
src={`${vite_url}/api/member/${data.id}/photo`}
|
||||||
alt="avatar"
|
alt="avatar"
|
||||||
className="rounded-circle img-fluid" style={{object_fit: 'contain'}}/>
|
className="rounded-circle img-fluid" style={{object_fit: 'contain'}}/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,3 +1,12 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
const vite_url = import.meta.env.VITE_URL;
|
||||||
|
|
||||||
|
export const apiAxios = axios.create({
|
||||||
|
baseURL: `${vite_url}/api`
|
||||||
|
});
|
||||||
|
apiAxios.defaults.headers.post['Accept'] = 'application/json; charset=UTF-8';
|
||||||
|
|
||||||
export function getCategoryFormBirthDate(birth_date, currentDate = new Date()) {
|
export function getCategoryFormBirthDate(birth_date, currentDate = new Date()) {
|
||||||
const currentSaison = getSaison(currentDate)
|
const currentSaison = getSaison(currentDate)
|
||||||
const birthYear = birth_date.getFullYear()
|
const birthYear = birth_date.getFullYear()
|
||||||
|
|||||||
@ -1,14 +1,10 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
const auth_url = import.meta.env.VITE_AUTH_URL;
|
|
||||||
const vite_url = import.meta.env.VITE_URL;
|
const vite_url = import.meta.env.VITE_URL;
|
||||||
const client_id = import.meta.env.VITE_CLIENT_ID;
|
|
||||||
|
|
||||||
const api_url = import.meta.env.VITE_API_URL;
|
|
||||||
|
|
||||||
export function check_validity(online_callback = () => {
|
export function check_validity(online_callback = () => {
|
||||||
}) {
|
}) {
|
||||||
return axios.get(`${api_url}/auth`).then(data => {
|
return axios.get(`${vite_url}/api/auth`).then(data => {
|
||||||
console.log(data.data)
|
console.log(data.data)
|
||||||
online_callback(data.data);
|
online_callback(data.data);
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
@ -18,7 +14,7 @@ export function check_validity(online_callback = () => {
|
|||||||
|
|
||||||
export function login() {
|
export function login() {
|
||||||
sessionStorage.setItem("next", window.location.href)
|
sessionStorage.setItem("next", window.location.href)
|
||||||
window.location.href = `${api_url}/auth/login`;
|
window.location.href = `${vite_url}/api/auth/login`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function login_redirect() {
|
export function login_redirect() {
|
||||||
@ -31,34 +27,6 @@ export function login_redirect() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function logout(token, refresh) {
|
export function logout() {
|
||||||
return axios.post(`${auth_url}/revoke`, {
|
window.location.href = `${vite_url}/api/logout`;
|
||||||
client_id: client_id,
|
}
|
||||||
token: refresh,
|
|
||||||
}, {
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${token}`,
|
|
||||||
"Accept": "application/x-www-form-urlencoded",
|
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
|
||||||
}
|
|
||||||
}).then(() => {
|
|
||||||
localStorage.removeItem("access_token")
|
|
||||||
localStorage.removeItem("refresh_token")
|
|
||||||
}).catch((err) => {
|
|
||||||
console.log(err)
|
|
||||||
// redirect_auth_page()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function redirect_auth_page() {
|
|
||||||
localStorage.removeItem("access_token");
|
|
||||||
localStorage.removeItem("refresh_token");
|
|
||||||
|
|
||||||
let state = ''
|
|
||||||
let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
|
||||||
for (let i = 0; i < 40; i++)
|
|
||||||
state += possible.charAt(Math.floor(Math.random() * possible.length))
|
|
||||||
localStorage.setItem("cb_" + state, window.location.href)
|
|
||||||
|
|
||||||
window.location.href = auth_url + `/auth?state=${state}&client_id=${encodeURIComponent(client_id)}&response_type=code&redirect_uri=${encodeURIComponent(vite_url + '/complete/auth/')}&scope=profile%20openid%20roles`
|
|
||||||
}
|
|
||||||
@ -10,6 +10,14 @@ export default ({mode}) => {
|
|||||||
server: {
|
server: {
|
||||||
host: process.env.VITE_INT_HOST,
|
host: process.env.VITE_INT_HOST,
|
||||||
port: process.env.VITE_INT_PORT,
|
port: process.env.VITE_INT_PORT,
|
||||||
|
|
||||||
|
proxy: {
|
||||||
|
// $VITE_URL/api* -> $VITE_API_URL/api*
|
||||||
|
"/api": {
|
||||||
|
target: process.env.VITE_API_URL,
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user