Commit 3c60ce32 authored by Wietse Kuipers's avatar Wietse Kuipers
Browse files

Refactor login() to redux-saga and more sensible structure

parent 97c98a38
# see http://editorconfig.org
root = true
[*]
end_of_line = lf
[*.{js,jsx}]
charset = utf-8
indent_style = space
indent_size = 2
import { AsyncStorage } from 'react-native';
import * as types from './actionTypes';
import { url, apiUrl } from '../url';
export const LOGIN = 'LOGIN_LOGIN';
export const LOGINPROGRESS = 'LOGINPROGRESS';
export const LOGINSUCCESS = 'LOGINSUCCESS';
export const LOGINFAILURE = 'LOGINFAILURE';
export const LOGOUT = 'LOGOUT';
const USERNAMEKEY = '@MyStore:username';
const TOKENKEY = '@MyStore:token';
const DISPLAYNAMEKEY = '@MyStore:displayName';
const PHOTOKEY = '@MyStore:photo';
const defaultAvatar = `${url}/static/members/images/default-avatar.jpg`;
export function resetLogin() {
......@@ -57,76 +58,8 @@ export function logoutSuccess() {
};
}
function getUserInfo(token) {
const data = {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Token ${token}`,
},
};
return fetch(`${apiUrl}/members/me/`, data)
.then(
response => response.json())
.then(
(responseJson) => {
const avatar = responseJson.photo === null ? defaultAvatar : responseJson.photo;
return {
photo: avatar,
displayName: responseJson.display_name,
};
},
)
.catch(
() => ({
photo: defaultAvatar,
displayName: 'Naamloos',
}),
);
}
export function login(user, pass) {
return (dispatch) => {
dispatch(loginProgress());
const data = {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: user,
password: pass,
}),
};
return fetch(`${apiUrl}/token-auth/`, data)
.then(
response => response.json())
.then(
(responseJson) => {
if (responseJson.token) {
const token = responseJson.token;
return getUserInfo(token)
.then(
userInfo => AsyncStorage.multiSet([
[USERNAMEKEY, user],
[TOKENKEY, token],
[DISPLAYNAMEKEY, userInfo.displayName],
[PHOTOKEY, userInfo.photo],
])
.then(() => dispatch(
loginSuccess(
user, token, userInfo.displayName, userInfo.photo,
)),
));
}
return dispatch(loginFailure());
})
.catch(() => dispatch(loginFailure()));
};
return { type: LOGIN, payload: { user, pass } };
}
export function logout() {
......
......@@ -3,16 +3,20 @@ import { AsyncStorage } from 'react-native';
import { applyMiddleware, combineReducers, createStore } from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';
import createSagaMiddleware from 'redux-saga';
import Moment from 'moment';
import 'moment/locale/nl';
import * as reducers from './reducers';
import sagas from './sagas';
import ReduxNavigator from './components/navigator';
import { loginSuccess } from './actions/login';
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);
const sagaMiddleware = createSagaMiddleware();
const reducer = combineReducers(reducers);
const store = createStoreWithMiddleware(reducer);
const store = createStoreWithMiddleware(reducer, applyMiddleware(thunk, sagaMiddleware));
sagaMiddleware.run(sagas);
const USERNAMEKEY = '@MyStore:username';
const TOKENKEY = '@MyStore:token';
......
import { all, fork } from 'redux-saga/effects';
import loginSaga from './login';
const sagas = function* sagas() {
yield all([
fork(loginSaga),
]);
};
export default sagas;
import { call, takeEvery, put } from 'redux-saga/effects';
import { AsyncStorage } from 'react-native';
import { apiRequest, url } from '../url';
import * as loginActions from '../actions/login';
const USERNAMEKEY = '@MyStore:username';
const TOKENKEY = '@MyStore:token';
const DISPLAYNAMEKEY = '@MyStore:displayName';
const PHOTOKEY = '@MyStore:photo';
const defaultAvatar = `${url}/static/members/images/default-avatar.jpg`;
const login = function* login(action) {
const { user, pass } = action.payload;
yield put(loginActions.loginProgress());
let data = {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: user,
password: pass,
}),
};
try {
let response = yield call(apiRequest, 'token-auth', data);
const { token } = response;
if (!token) {
throw Error();
}
data = {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Token ${token}`,
},
};
response = yield call(apiRequest, 'members/me', data);
const displayName = response.display_name;
const avatar = response.photo === null ? defaultAvatar : response.photo;
yield call(AsyncStorage.multiSet, [
[USERNAMEKEY, user],
[TOKENKEY, token],
[DISPLAYNAMEKEY, displayName],
[PHOTOKEY, avatar],
]);
yield put(loginActions.loginSuccess(
user, token, displayName, avatar,
));
} catch (error) {
yield put(loginActions.loginFailure());
}
};
const loginSaga = function* loginSaga() {
yield takeEvery(loginActions.LOGIN, login);
};
export default loginSaga;
......@@ -6,3 +6,5 @@ if (__DEV__) { // eslint-disable-line no-undef
export const url = server;
export const apiUrl = `${server}/api/v1`;
export const pizzaUrl = 'https://pizza.thalia.nu';
export const apiRequest = (route, data) => fetch(`${apiUrl}/${route}/`, data).then(response => response.json());
......@@ -4069,9 +4069,9 @@ react-native-vector-icons@^4.0.1:
prop-types "^15.5.10"
yargs "^8.0.2"
react-native@0.48.1:
version "0.48.1"
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.48.1.tgz#052ba5a86d3bdb748c288124248727d02b1c0939"
react-native@0.48.3:
version "0.48.3"
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.48.3.tgz#ec17a66929eb292512b14c091cf260b25e2fba18"
dependencies:
absolute-path "^0.0.0"
art "^0.10.0"
......@@ -4278,6 +4278,10 @@ rechoir@^0.6.2:
dependencies:
resolve "^1.1.6"
redux-saga@^0.15.6:
version "0.15.6"
resolved "https://registry.yarnpkg.com/redux-saga/-/redux-saga-0.15.6.tgz#8638dc522de6c6c0a496fe8b2b5466287ac2dc4d"
redux-thunk@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment