auth work

This commit is contained in:
Romulus21
2024-07-17 07:09:04 +02:00
parent 6be48846b0
commit a34eadb51f
13 changed files with 1125 additions and 1042 deletions

View File

@@ -15,9 +15,7 @@ class Reset extends Mailable
/** /**
* Create a new message instance. * Create a new message instance.
*/ */
public function __construct(private readonly string $token) public function __construct(private readonly string $token) {}
{
}
/** /**
* Get the message envelope. * Get the message envelope.
@@ -37,7 +35,7 @@ class Reset extends Mailable
return new Content( return new Content(
markdown: 'mails.reset_password', markdown: 'mails.reset_password',
with: [ with: [
'link' => config('gpao.front_url').'/reset/'.$this->token, 'link' => config('app.url').'/reset/'.$this->token,
] ]
); );
} }

862
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,26 +8,26 @@
"lint-fix": "eslint ./ --fix" "lint-fix": "eslint ./ --fix"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^18.2.73", "@types/react": "^18.3.3",
"@types/react-dom": "^18.2.23", "@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.4.0", "@typescript-eslint/eslint-plugin": "^7.16.1",
"@typescript-eslint/parser": "^7.4.0", "@typescript-eslint/parser": "^7.16.1",
"@vitejs/plugin-react": "^4.2.1", "@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"axios": "^1.6.8", "axios": "^1.7.2",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-plugin-react": "^7.34.1", "eslint-plugin-react": "^7.34.4",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-tailwindcss": "^3.15.1", "eslint-plugin-tailwindcss": "^3.17.4",
"laravel-vite-plugin": "^1.0.2", "laravel-vite-plugin": "^1.0.5",
"postcss": "^8.4.38", "postcss": "^8.4.39",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.6",
"typescript": "^5.4.3", "typescript": "^5.5.3",
"vite": "^5.2.7" "vite": "^5.3.4"
}, },
"dependencies": { "dependencies": {
"react": "^18.2.0", "react": "^18.3.1",
"react-dom": "^18.2.0", "react-dom": "^18.3.1",
"react-router-dom": "^6.22.3" "react-router-dom": "^6.25.0"
} }
} }

View File

@@ -26,8 +26,8 @@
<env name="APP_ENV" value="testing"/> <env name="APP_ENV" value="testing"/>
<env name="BCRYPT_ROUNDS" value="4"/> <env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_DRIVER" value="redis"/> <env name="CACHE_DRIVER" value="redis"/>
<!-- <env name="DB_CONNECTION" value="sqlite"/> --> <env name="DB_CONNECTION" value="sqlite"/>
<!-- <env name="DB_DATABASE" value=":memory:"/> --> <env name="DB_DATABASE" value=":memory:"/>
<env name="MAIL_MAILER" value="array"/> <env name="MAIL_MAILER" value="array"/>
<env name="PULSE_ENABLED" value="false"/> <env name="PULSE_ENABLED" value="false"/>
<env name="QUEUE_CONNECTION" value="sync"/> <env name="QUEUE_CONNECTION" value="sync"/>

1181
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -30,8 +30,9 @@ export const AuthUserProvider = ({children}: PropsWithChildren) => {
} catch (error) { } catch (error) {
// @ts-expect-error 401 error to redirect // @ts-expect-error 401 error to redirect
if (error.response.status === 401) { if (error.response.status === 401) {
const page = window.location.pathname.split('/')[1]
if (!['connexion', 'sinscrire', 'reset'].includes(page)) {
console.info('no user login') console.info('no user login')
if (!['/connexion', '/sinscrire'].includes(window.location.pathname)) {
window.location.href = '/connexion' window.location.href = '/connexion'
} }
} }

View File

@@ -14,9 +14,13 @@ const useAxiosTools = (isLoading = false) => {
const errorCatch = (error: Error|AxiosError|unknown) => { const errorCatch = (error: Error|AxiosError|unknown) => {
if (axios.isAxiosError(error)) { if (axios.isAxiosError(error)) {
(error.response?.status === 422) if (error.response?.status === 422) {
? displayFormErrors(error) displayFormErrors(error)
: setError(error.response?.data.message || error.message) } else if (error.response?.status === 401) {
console.log('not authorise')
} else {
setError(error.response?.data.message || error.message)
}
} else if (error instanceof Error) { } else if (error instanceof Error) {
setError(error.message) setError(error.message)
} }

View File

@@ -14,7 +14,7 @@ interface TrackerProps {
export const TrackerProvider = ({children}: PropsWithChildren) => { export const TrackerProvider = ({children}: PropsWithChildren) => {
const [currentTimeTracker, setCurrentTimeTracker] = useState<timeTracker|null>(null) const [currentTimeTracker, setCurrentTimeTracker] = useState<timeTracker|null>(null)
const {axiosGet, axiosPost, axiosDelete} = useAxiosTools() const {axiosGet, axiosPost, axiosDelete, errorCatch} = useAxiosTools()
useEffect(() => { useEffect(() => {
fetchCurrentTimeTracker() fetchCurrentTimeTracker()
@@ -25,7 +25,7 @@ export const TrackerProvider = ({children}: PropsWithChildren) => {
const res = await axiosGet(`/api/time-trackers/user`) const res = await axiosGet(`/api/time-trackers/user`)
setCurrentTimeTracker(res.data) setCurrentTimeTracker(res.data)
} catch (error) { } catch (error) {
console.error(error) errorCatch(error)
} }
} }

View File

@@ -45,6 +45,11 @@ const Login = () => {
placeholder="******" placeholder="******"
value={password} value={password}
onChange={event => setPassword(event.target.value)}>Mot de passe</Field> onChange={event => setPassword(event.target.value)}>Mot de passe</Field>
<Field type="hidden"
value={1}
name="form_info" onChange={() => setPassword('')}/>
<button type="submit" className="btn-primary mt-5 block w-full text-lg">Valider</button> <button type="submit" className="btn-primary mt-5 block w-full text-lg">Valider</button>
<Link to="/mot-de-passe-oubliee" className="mt-2 inline-block">Mot de passe oublié ?</Link> <Link to="/mot-de-passe-oubliee" className="mt-2 inline-block">Mot de passe oublié ?</Link>
</form> </form>

View File

@@ -3,12 +3,10 @@ import Field from "../../components/Field"
import axios from "axios" import axios from "axios"
import {useNavigate} from "react-router-dom" import {useNavigate} from "react-router-dom"
import Card from "../../components/Card" import Card from "../../components/Card"
import useAuthUser from "../../hooks/AuthUser"
const Register = () => { const Register = () => {
const navigate = useNavigate() const navigate = useNavigate()
const {setAuthUser} = useAuthUser()
const [name, setName] = useState('') const [name, setName] = useState('')
const [email, setEmail] = useState('') const [email, setEmail] = useState('')
const [password, setPassword] = useState('') const [password, setPassword] = useState('')
@@ -17,9 +15,8 @@ const Register = () => {
event.preventDefault() event.preventDefault()
try { try {
await axios.get('/sanctum/csrf-cookie') await axios.get('/sanctum/csrf-cookie')
const res = await axios.post('/api/register', {name, email, password}) await axios.post('/api/register', {name, email, password})
setAuthUser(res.data) navigate('/connexion')
navigate('/')
} catch (e) { } catch (e) {
console.error(e) console.error(e)
} }

View File

@@ -10,6 +10,8 @@ import Register from "./Auth/Register"
import ToDoShow from "./ToDos/ToDoShow" import ToDoShow from "./ToDos/ToDoShow"
import TimeTrackersIndex from "./TimeTrackersIndex" import TimeTrackersIndex from "./TimeTrackersIndex"
import {env} from "../utilities/env" import {env} from "../utilities/env"
import Reset from "./Auth/Reset"
import ForgotPassword from "./Auth/ForgotPassword"
const Router = () => { const Router = () => {
@@ -26,6 +28,8 @@ const Router = () => {
<Route path="/connexion" element={<Login />} /> <Route path="/connexion" element={<Login />} />
{env.VITE_REGISTER_DISABLED === 'false' && <Route path="/sinscrire" element={<Register />} />} {env.VITE_REGISTER_DISABLED === 'false' && <Route path="/sinscrire" element={<Register />} />}
<Route path="/todos/:id" element={<ToDoShow />} /> <Route path="/todos/:id" element={<ToDoShow />} />
<Route path="/mot-de-passe-oubliee" element={<ForgotPassword />} />
<Route path="/reset/:token" element={<Reset />} />
<Route path="/times" element={<TimeTrackersIndex />} /> <Route path="/times" element={<TimeTrackersIndex />} />
</Routes> </Routes>
</Suspense> </Suspense>

View File

@@ -0,0 +1,7 @@
<?php
return [
'exists' => 'Le champ :attribute est invalide.',
'invalid_credentials' => 'Identifiant ou mot de passe incorrect.',
'password_rules' => 'Le mot de passe doit contenir des lettres majuscules et minuscules, des chiffres et au moins 8 caractères.',
];

View File

@@ -25,8 +25,8 @@ test('invalid credential return an error', function () {
]) ])
->assertStatus(422) ->assertStatus(422)
->assertJson([ ->assertJson([
'message' => 'Invalid credentials.', 'message' => 'Identifiant ou mot de passe incorrect.',
'errors' => ['form_info' => 'Invalid credentials.'], 'errors' => ['form_info' => 'Identifiant ou mot de passe incorrect.'],
]); ]);
}); });
@@ -201,8 +201,8 @@ test('reset action need specific credentials', function () {
]) ])
->assertStatus(422) ->assertStatus(422)
->assertJson([ ->assertJson([
'message' => 'The selected token is invalid.', 'message' => 'Le champ token est invalide.',
'errors' => ['token' => ['The selected token is invalid.']], 'errors' => ['token' => ['Le champ token est invalide.']],
]); ]);
DB::table('password_reset_tokens') DB::table('password_reset_tokens')
@@ -221,7 +221,7 @@ test('reset action need specific credentials', function () {
]) ])
->assertStatus(422) ->assertStatus(422)
->assertJson([ ->assertJson([
'message' => 'Invalid credentials.', 'message' => 'Identifiant ou mot de passe incorrect.',
'errors' => ['form_info' => 'Invalid credentials.'], 'errors' => ['form_info' => 'Identifiant ou mot de passe incorrect.'],
]); ]);
}); });