mirror of
				https://github.com/elyby/accounts-frontend.git
				synced 2025-05-31 14:11:58 +05:30 
			
		
		
		
	#126: slightly refactored login and jwt token logic
This commit is contained in:
		@@ -2,6 +2,7 @@ import { routeActions } from 'react-router-redux';
 | 
			
		||||
 | 
			
		||||
import { updateUser, logout as logoutUser, changePassword as changeUserPassword, authenticate } from 'components/user/actions';
 | 
			
		||||
import request from 'services/request';
 | 
			
		||||
import authentication from 'services/api/authentication';
 | 
			
		||||
 | 
			
		||||
export function login({login = '', password = '', rememberMe = false}) {
 | 
			
		||||
    const PASSWORD_REQUIRED = 'error.password_required';
 | 
			
		||||
@@ -9,28 +10,21 @@ export function login({login = '', password = '', rememberMe = false}) {
 | 
			
		||||
    const ACTIVATION_REQUIRED = 'error.account_not_activated';
 | 
			
		||||
 | 
			
		||||
    return wrapInLoader((dispatch) =>
 | 
			
		||||
        request.post(
 | 
			
		||||
            '/api/authentication/login',
 | 
			
		||||
        authentication.login(
 | 
			
		||||
            {login, password, rememberMe}
 | 
			
		||||
        )
 | 
			
		||||
        .then((resp) => {
 | 
			
		||||
            dispatch(updateUser({
 | 
			
		||||
                isGuest: false,
 | 
			
		||||
                token: resp.jwt
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
            return dispatch(authenticate(resp.jwt));
 | 
			
		||||
        })
 | 
			
		||||
        .then(authHandler(dispatch))
 | 
			
		||||
        .catch((resp) => {
 | 
			
		||||
            if (resp.errors.login === ACTIVATION_REQUIRED) {
 | 
			
		||||
                return dispatch(needActivation());
 | 
			
		||||
            } else if (resp.errors.password === PASSWORD_REQUIRED) {
 | 
			
		||||
                return dispatch(updateUser({
 | 
			
		||||
                    username: login,
 | 
			
		||||
                    email: login
 | 
			
		||||
                }));
 | 
			
		||||
            } else if (resp.errors) {
 | 
			
		||||
                if (resp.errors.login === LOGIN_REQUIRED && password) {
 | 
			
		||||
            if (resp.errors) {
 | 
			
		||||
                if (resp.errors.password === PASSWORD_REQUIRED) {
 | 
			
		||||
                    return dispatch(updateUser({
 | 
			
		||||
                        username: login,
 | 
			
		||||
                        email: login
 | 
			
		||||
                    }));
 | 
			
		||||
                } else if (resp.errors.login === ACTIVATION_REQUIRED) {
 | 
			
		||||
                    return dispatch(needActivation());
 | 
			
		||||
                } else if (resp.errors.login === LOGIN_REQUIRED && password) {
 | 
			
		||||
                    // return to the first step
 | 
			
		||||
                    dispatch(logout());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -76,14 +70,7 @@ export function recoverPassword({
 | 
			
		||||
            '/api/authentication/recover-password',
 | 
			
		||||
            {key, newPassword, newRePassword}
 | 
			
		||||
        )
 | 
			
		||||
        .then((resp) => {
 | 
			
		||||
            dispatch(updateUser({
 | 
			
		||||
                isGuest: false,
 | 
			
		||||
                isActive: true
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
            return dispatch(authenticate(resp.jwt));
 | 
			
		||||
        })
 | 
			
		||||
        .then(authHandler(dispatch))
 | 
			
		||||
        .catch(validationErrorsHandler(dispatch, '/forgot-password'))
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
@@ -118,14 +105,7 @@ export function activate({key = ''}) {
 | 
			
		||||
            '/api/signup/confirm',
 | 
			
		||||
            {key}
 | 
			
		||||
        )
 | 
			
		||||
        .then((resp) => {
 | 
			
		||||
            dispatch(updateUser({
 | 
			
		||||
                isGuest: false,
 | 
			
		||||
                isActive: true
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
            return dispatch(authenticate(resp.jwt));
 | 
			
		||||
        })
 | 
			
		||||
        .then(authHandler(dispatch))
 | 
			
		||||
        .catch(validationErrorsHandler(dispatch, '/resend-activation'))
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
@@ -341,6 +321,10 @@ function needActivation() {
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function authHandler(dispatch) {
 | 
			
		||||
    return (resp) => dispatch(authenticate(resp.access_token, resp.refresh_token));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function validationErrorsHandler(dispatch, repeatUrl) {
 | 
			
		||||
    return (resp) => {
 | 
			
		||||
        if (resp.errors) {
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@ export default class PasswordBody extends BaseAuthBody {
 | 
			
		||||
                        {user.email || user.username}
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
                <Input {...this.bindField('password')}
 | 
			
		||||
                    icon="key"
 | 
			
		||||
                    type="password"
 | 
			
		||||
@@ -40,7 +41,7 @@ export default class PasswordBody extends BaseAuthBody {
 | 
			
		||||
                />
 | 
			
		||||
 | 
			
		||||
                <Checkbox {...this.bindField('rememberMe')}
 | 
			
		||||
                    defaultChecked={true}
 | 
			
		||||
                    defaultChecked
 | 
			
		||||
                    label={messages.rememberMe}
 | 
			
		||||
                />
 | 
			
		||||
            </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ export default class User {
 | 
			
		||||
            id: null,
 | 
			
		||||
            uuid: null,
 | 
			
		||||
            token: '',
 | 
			
		||||
            refreshToken: '',
 | 
			
		||||
            username: '',
 | 
			
		||||
            email: '',
 | 
			
		||||
            // will contain user's email or masked email
 | 
			
		||||
 
 | 
			
		||||
@@ -95,13 +95,21 @@ export function changePassword({
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export function authenticate(token) {
 | 
			
		||||
export function authenticate(token, refreshToken) {
 | 
			
		||||
    if (!token || token.split('.').length !== 3) {
 | 
			
		||||
        throw new Error('Invalid token');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (dispatch) => {
 | 
			
		||||
        request.setAuthToken(token);
 | 
			
		||||
        return dispatch(fetchUserData());
 | 
			
		||||
 | 
			
		||||
        return dispatch(fetchUserData()).then((resp) => {
 | 
			
		||||
            dispatch(updateUser({
 | 
			
		||||
                isGuest: false,
 | 
			
		||||
                token,
 | 
			
		||||
                refreshToken
 | 
			
		||||
            }));
 | 
			
		||||
            return resp;
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								src/services/api/authentication.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/services/api/authentication.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
import request from 'services/request';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    login({
 | 
			
		||||
        login = '',
 | 
			
		||||
        password = '',
 | 
			
		||||
        rememberMe = false
 | 
			
		||||
    }) {
 | 
			
		||||
        return request.post(
 | 
			
		||||
            '/api/authentication/login',
 | 
			
		||||
            {login, password, rememberMe}
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
@@ -14,11 +14,12 @@ export default class PasswordState extends AbstractState {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    resolve(context, {password}) {
 | 
			
		||||
    resolve(context, {password, rememberMe}) {
 | 
			
		||||
        const {user} = context.getState();
 | 
			
		||||
 | 
			
		||||
        context.run('login', {
 | 
			
		||||
            password,
 | 
			
		||||
            rememberMe,
 | 
			
		||||
            login: user.email || user.username
 | 
			
		||||
        })
 | 
			
		||||
        .then(() => context.setState(new CompleteState()));
 | 
			
		||||
 
 | 
			
		||||
@@ -48,6 +48,7 @@ describe('PasswordState', () => {
 | 
			
		||||
        (function() {
 | 
			
		||||
            const expectedLogin = 'login';
 | 
			
		||||
            const expectedPassword = 'password';
 | 
			
		||||
            const expectedRememberMe = true;
 | 
			
		||||
 | 
			
		||||
            const testWith = (user) => {
 | 
			
		||||
                it(`should call login with email or username and password. User: ${JSON.stringify(user)}`, () => {
 | 
			
		||||
@@ -58,11 +59,12 @@ describe('PasswordState', () => {
 | 
			
		||||
                        'login',
 | 
			
		||||
                        sinon.match({
 | 
			
		||||
                            login: expectedLogin,
 | 
			
		||||
                            password: expectedPassword
 | 
			
		||||
                            password: expectedPassword,
 | 
			
		||||
                            rememberMe: expectedRememberMe,
 | 
			
		||||
                        })
 | 
			
		||||
                    ).returns({then() {}});
 | 
			
		||||
 | 
			
		||||
                    state.resolve(context, {password: expectedPassword});
 | 
			
		||||
                    state.resolve(context, {password: expectedPassword, rememberMe: expectedRememberMe});
 | 
			
		||||
                });
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user