Ajout page d'authentification
This commit is contained in:
parent
72e328ea1c
commit
3aa8ab987b
|
@ -2,6 +2,7 @@
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Http\DataResponse;
|
use App\Http\DataResponse;
|
||||||
|
use App\Http\ErrorResponse;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
@ -12,10 +13,19 @@ class SecurityController extends Controller
|
||||||
/**
|
/**
|
||||||
* @Route("/api/v1/login", name="api_v1_login", methods={"POST"})
|
* @Route("/api/v1/login", name="api_v1_login", methods={"POST"})
|
||||||
*/
|
*/
|
||||||
public function login(Request $request)
|
public function login()
|
||||||
{
|
{
|
||||||
$user = $this->getUser();
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
if ($user == null) {
|
||||||
|
return new ErrorResponse(
|
||||||
|
0,
|
||||||
|
"Identifiants invalides",
|
||||||
|
null,
|
||||||
|
401,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return new DataResponse([
|
return new DataResponse([
|
||||||
'username' => $user->getUsername(),
|
'username' => $user->getUsername(),
|
||||||
'roles' => $user->getRoles(),
|
'roles' => $user->getRoles(),
|
||||||
|
|
|
@ -5107,7 +5107,8 @@
|
||||||
},
|
},
|
||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
|
@ -5125,11 +5126,13 @@
|
||||||
},
|
},
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
|
@ -5142,15 +5145,18 @@
|
||||||
},
|
},
|
||||||
"code-point-at": {
|
"code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
@ -5253,7 +5259,8 @@
|
||||||
},
|
},
|
||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
|
@ -5263,6 +5270,7 @@
|
||||||
"is-fullwidth-code-point": {
|
"is-fullwidth-code-point": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
|
@ -5275,17 +5283,20 @@
|
||||||
"minimatch": {
|
"minimatch": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.9.0",
|
"version": "2.9.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.2",
|
"safe-buffer": "^5.1.2",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
|
@ -5302,6 +5313,7 @@
|
||||||
"mkdirp": {
|
"mkdirp": {
|
||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
|
@ -5382,7 +5394,8 @@
|
||||||
},
|
},
|
||||||
"number-is-nan": {
|
"number-is-nan": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
|
@ -5392,6 +5405,7 @@
|
||||||
"once": {
|
"once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
|
@ -5467,7 +5481,8 @@
|
||||||
},
|
},
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"safer-buffer": {
|
"safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
|
@ -5497,6 +5512,7 @@
|
||||||
"string-width": {
|
"string-width": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
|
@ -5514,6 +5530,7 @@
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^2.0.0"
|
"ansi-regex": "^2.0.0"
|
||||||
}
|
}
|
||||||
|
@ -5552,11 +5569,13 @@
|
||||||
},
|
},
|
||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
export const LOGIN_REQUEST = 'LOGIN_REQUEST'
|
||||||
|
export const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
|
||||||
|
export const LOGIN_FAILURE = 'LOGIN_FAILURE';
|
||||||
|
|
||||||
|
export function login(username, password) {
|
||||||
|
return { type: LOGIN_REQUEST, username, password }
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loginFailure(username, error) {
|
||||||
|
return { type: LOGIN_FAILURE, username, error }
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loginSuccess(username) {
|
||||||
|
return { type: LOGIN_SUCCESS, username }
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LOGOUT_REQUEST = 'LOGOUT_REQUEST'
|
||||||
|
export const LOGOUT_SUCCESS = 'LOGOUT_SUCCESS';
|
||||||
|
export const LOGOUT_FAILURE = 'LOGOUT_FAILURE';
|
||||||
|
|
||||||
|
export function logout(username, password) {
|
||||||
|
return { type: LOGOUT_REQUEST, username, password }
|
||||||
|
}
|
||||||
|
|
||||||
|
export function logoutFailure(username, error) {
|
||||||
|
return { type: LOGOUT_FAILURE, username, error }
|
||||||
|
}
|
||||||
|
|
||||||
|
export function logoutSuccess(username) {
|
||||||
|
return { type: LOGOUT_SUCCESS, username }
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ import { hot } from 'react-hot-loader'
|
||||||
import { HashRouter } from 'react-router-dom' // ou BrowserRouter
|
import { HashRouter } from 'react-router-dom' // ou BrowserRouter
|
||||||
import { Route, Switch, Redirect } from 'react-router'
|
import { Route, Switch, Redirect } from 'react-router'
|
||||||
import HomePage from './pages/home';
|
import HomePage from './pages/home';
|
||||||
|
import { ConnectedLoginPage as LoginPage } from './pages/login';
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
render () {
|
render () {
|
||||||
|
@ -10,6 +11,7 @@ class App extends Component {
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<HashRouter>
|
<HashRouter>
|
||||||
<Switch>
|
<Switch>
|
||||||
|
<Route path='/login' exact component={LoginPage} />
|
||||||
<Route path='/home' exact component={HomePage} />
|
<Route path='/home' exact component={HomePage} />
|
||||||
<Route component={() => <Redirect to="/home" />} />
|
<Route component={() => <Redirect to="/home" />} />
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
import React, { useState, useEffect } from 'react'
|
||||||
|
import Page from './page';
|
||||||
|
import { login } from '../actions/auth.actions';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
export function LoginPage({ dispatch, isLoggedIn, history }) {
|
||||||
|
|
||||||
|
const [ formData, setFormData ] = useState({username: '', password: ''});
|
||||||
|
const onUsernameChange = evt => setFormData({ ...formData, username: evt.target.value });
|
||||||
|
const onPasswordChange = evt => setFormData({ ...formData, password: evt.target.value });
|
||||||
|
const onSubmit = evt => {
|
||||||
|
evt.preventDefault();
|
||||||
|
const { username, password } = formData;
|
||||||
|
dispatch(login(username, password));
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isLoggedIn) history.push('/home');
|
||||||
|
}, [isLoggedIn]);
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page>
|
||||||
|
<div className="section">
|
||||||
|
<div className="columns">
|
||||||
|
<div className="column is-4 is-offset-4">
|
||||||
|
<div className="box">
|
||||||
|
<div className="field">
|
||||||
|
<label className="label">Nom d'utilisateur</label>
|
||||||
|
<div className="control">
|
||||||
|
<input
|
||||||
|
value={formData.username}
|
||||||
|
onChange={onUsernameChange}
|
||||||
|
type="text" className="input" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="field">
|
||||||
|
<label className="label">Mot de passe</label>
|
||||||
|
<div className="control">
|
||||||
|
<input
|
||||||
|
value={formData.password}
|
||||||
|
onChange={onPasswordChange}
|
||||||
|
className="input" type="password" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="field is-grouped is-grouped-right">
|
||||||
|
<p className="control">
|
||||||
|
<button onClick={onSubmit}
|
||||||
|
className="button is-primary">
|
||||||
|
Se connecter
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Page>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps({ session }) {
|
||||||
|
return { isLoggedIn: session.isLoggedIn };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ConnectedLoginPage = connect(mapStateToProps)(LoginPage);
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { LOGIN_SUCCESS } from "../actions/auth.actions";
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
isLoggedIn: false,
|
||||||
|
user: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export function sessionReducer(state = initialState, action) {
|
||||||
|
switch(action.type) {
|
||||||
|
case LOGIN_SUCCESS:
|
||||||
|
return handleLoginSuccess(state, action);
|
||||||
|
};
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleLoginSuccess(state, action) {
|
||||||
|
return {
|
||||||
|
...state.user,
|
||||||
|
isLoggedIn: true,
|
||||||
|
user: {
|
||||||
|
username: action.username,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { call, put } from 'redux-saga/effects';
|
||||||
|
import { loginFailure, loginSuccess } from '../actions/auth.actions';
|
||||||
|
|
||||||
|
export function* loginSaga(action) {
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = yield call(doLogin, action.username, action.password);
|
||||||
|
} catch(err) {
|
||||||
|
yield put(loginFailure(action.username, err));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('error' in result) {
|
||||||
|
yield put(loginFailure(action.username, result.error));
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
yield put(loginSuccess(action.username));
|
||||||
|
}
|
||||||
|
|
||||||
|
function doLogin(username, password) {
|
||||||
|
return fetch('http://localhost:8001/api/v1/login', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
username: username,
|
||||||
|
password: password
|
||||||
|
}),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
mode: 'cors',
|
||||||
|
credentials: 'include'
|
||||||
|
}).then(res => res.json())
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
import { all, takeLatest } from 'redux-saga/effects';
|
import { all, takeLatest } from 'redux-saga/effects';
|
||||||
|
import { LOGIN_REQUEST } from '../actions/auth.actions';
|
||||||
|
import { loginSaga} from './auth.sagas';
|
||||||
|
|
||||||
export default function* rootSaga() {
|
export default function* rootSaga() {
|
||||||
yield all([
|
yield all([
|
||||||
|
takeLatest(LOGIN_REQUEST, loginSaga),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import { createStore, applyMiddleware, combineReducers, compose } from 'redux'
|
import { createStore, applyMiddleware, combineReducers, compose } from 'redux'
|
||||||
import createSagaMiddleware from 'redux-saga'
|
import createSagaMiddleware from 'redux-saga'
|
||||||
import rootSaga from '../sagas/root'
|
import rootSaga from '../sagas/root'
|
||||||
|
import { sessionReducer } from '../reducers/session.reducers';
|
||||||
|
|
||||||
const sagaMiddleware = createSagaMiddleware()
|
const sagaMiddleware = createSagaMiddleware()
|
||||||
|
|
||||||
const rootReducer = combineReducers({
|
const rootReducer = combineReducers({
|
||||||
// Ajouter vos reducers ici
|
session: sessionReducer,
|
||||||
});
|
});
|
||||||
|
|
||||||
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
|
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
|
||||||
|
|
Loading…
Reference in New Issue