function* authenticate(credentials) {
try {
const {data} = yield call(requestLogin, credentials);
storeAuthToken(data.token);
yield* [
put(loginSuccess()),
put(storeMe(data.me)),
put(push(ROUTER_PROFILE_URL))
];
} catch (error) {
let errorMessage = '';
if (error.response) {
errorMessage = parseResponseErrors(error.response);
} else {
errorMessage = [error.toString()];
}
yield put(loginError(errorMessage));
} finally {
if (yield cancelled()) {
window.location = '/';
}
}
}
function* loginFlow() {
while (true) {
let authToken = getAuthToken();
let authenticateTask = null;
// If we already have the token we don't want to call authenticate.
// This happens when a user, that's already logged in, opens a page from the app
// We still want to run the saga, waiting for logout requests
if (!authToken) {
const {credentials} = yield take(LOGIN_REQUEST);
authenticateTask = yield fork(authenticate, credentials);
}
const action = yield take([LOGOUT_REQUEST, LOGIN_ERROR]);
// If there is an error with the credentials we don't want to run the following logic.
// But we want to go back listening for login requests.
if (action.type === LOGIN_ERROR) {
continue;
}
// If the user is trying to log out before logging in is finished we cancel the authentication.
// This is a very rare race condition that's hard to reproduce, but still, we handle that.
if (authenticateTask) {
yield cancel(authenticateTask);
}
// If we are logging in for the first time, we won't have authToken
// That's why we try to get it again.
if (!authToken) {
authToken = getAuthToken();
}
// If there is a racing condition and the login is not finished but you are trying to logout
// we won't call `requestLogout` (which will return us 403 Permission Denied) since you can't really
// log out if you haven't log in.
if (authToken) {
removeAuthToken();
yield call(requestLogout, authToken);
// We refresh on logout in order to clear everything from the stores, the hard way.
// This can prevent from some bugs due to improperly unmounted components.
window.location = '/';
}
}
}
Last active
February 1, 2018 16:00
-
-
Save martin056/4a4b135ae299d6c1fdbf52f4f563494a to your computer and use it in GitHub Desktop.
Implementation of login flow using redux-saga.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment