auth work
This commit is contained in:
@@ -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
862
composer.lock
generated
File diff suppressed because it is too large
Load Diff
34
package.json
34
package.json
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
1181
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -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) {
|
||||||
console.info('no user login')
|
const page = window.location.pathname.split('/')[1]
|
||||||
if (!['/connexion', '/sinscrire'].includes(window.location.pathname)) {
|
if (!['connexion', 'sinscrire', 'reset'].includes(page)) {
|
||||||
|
console.info('no user login')
|
||||||
window.location.href = '/connexion'
|
window.location.href = '/connexion'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,19 +34,24 @@ const Login = () => {
|
|||||||
</h1>
|
</h1>
|
||||||
{errorLabel()}
|
{errorLabel()}
|
||||||
|
|
||||||
<Field type="email"
|
<Field type="email"
|
||||||
name="email"
|
name="email"
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
value={email}
|
value={email}
|
||||||
onChange={event => setEmail(event.target.value)}
|
onChange={event => setEmail(event.target.value)}
|
||||||
autoFocus>Email</Field>
|
autoFocus>Email</Field>
|
||||||
<Field type="password"
|
<Field type="password"
|
||||||
name="password"
|
name="password"
|
||||||
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>
|
||||||
<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>
|
<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>
|
||||||
|
<Link to="/mot-de-passe-oubliee" className="mt-2 inline-block">Mot de passe oublié ?</Link>
|
||||||
</form>
|
</form>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
7
resources/lang/fr/validation.php
Normal file
7
resources/lang/fr/validation.php
Normal 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.',
|
||||||
|
];
|
||||||
@@ -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.'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user