sforkowany z mirror/soapbox
Merge branch 'invalid-auth-fix' into 'develop'
Auth: clear `me` when ME_FETCH_SKIP is dispatched See merge request soapbox-pub/soapbox-fe!588actually-fix-tabs-bar
commit
b6b95f06be
|
@ -8,6 +8,7 @@ import {
|
|||
VERIFY_CREDENTIALS_FAIL,
|
||||
SWITCH_ACCOUNT,
|
||||
} from 'soapbox/actions/auth';
|
||||
import { ME_FETCH_SKIP } from 'soapbox/actions/me';
|
||||
|
||||
describe('auth reducer', () => {
|
||||
it('should return the initial state', () => {
|
||||
|
@ -250,4 +251,13 @@ describe('auth reducer', () => {
|
|||
expect(result.get('me')).toEqual('5678');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ME_FETCH_SKIP', () => {
|
||||
it('sets `me` to null', () => {
|
||||
const state = fromJS({ me: '1234' });
|
||||
const action = { type: ME_FETCH_SKIP };
|
||||
const result = reducer(state, action);
|
||||
expect(result.get('me')).toEqual(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,7 +7,8 @@ import {
|
|||
VERIFY_CREDENTIALS_SUCCESS,
|
||||
VERIFY_CREDENTIALS_FAIL,
|
||||
} from '../actions/auth';
|
||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||
import { ME_FETCH_SKIP } from '../actions/me';
|
||||
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
|
||||
|
||||
const defaultState = ImmutableMap({
|
||||
app: ImmutableMap(),
|
||||
|
@ -16,31 +17,50 @@ const defaultState = ImmutableMap({
|
|||
me: null,
|
||||
});
|
||||
|
||||
const validId = id => typeof id === 'string' && id !== 'null' && id !== 'undefined';
|
||||
|
||||
const getSessionUser = () => {
|
||||
const id = sessionStorage.getItem('soapbox:auth:me');
|
||||
if (id && typeof id === 'string' && id !== 'null' && id !== 'undefined') {
|
||||
return id;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return validId(id) ? id : undefined;
|
||||
};
|
||||
|
||||
const sessionUser = getSessionUser();
|
||||
const localState = fromJS(JSON.parse(localStorage.getItem('soapbox:auth')));
|
||||
|
||||
// Checks if the user has an ID and access token
|
||||
const validUser = user => {
|
||||
try {
|
||||
return validId(user.get('id')) && validId(user.get('access_token'));
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Finds the first valid user in the state
|
||||
const firstValidUser = state => state.get('users', ImmutableMap()).find(validUser);
|
||||
|
||||
// If `me` doesn't match an existing user, attempt to shift it.
|
||||
const maybeShiftMe = state => {
|
||||
const users = state.get('users', ImmutableMap());
|
||||
const me = state.get('me');
|
||||
|
||||
if (!users.get(me)) {
|
||||
return state.set('me', users.first(ImmutableMap()).get('id', null));
|
||||
if (!validUser(users.get(me))) {
|
||||
const nextUser = firstValidUser(state);
|
||||
return state.set('me', nextUser ? nextUser.get('id') : null);
|
||||
} else {
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
const setSessionUser = state => state.update('me', null, me => sessionUser || me);
|
||||
// Set the user from the session or localStorage, whichever is valid first
|
||||
const setSessionUser = state => state.update('me', null, me => {
|
||||
const user = ImmutableList([
|
||||
state.getIn(['users', sessionUser]),
|
||||
state.getIn(['users', me]),
|
||||
]).find(validUser);
|
||||
|
||||
return user ? user.get('id') : null;
|
||||
});
|
||||
|
||||
// Upgrade the initial state
|
||||
const migrateLegacy = state => {
|
||||
|
@ -63,6 +83,24 @@ const migrateLegacy = state => {
|
|||
});
|
||||
};
|
||||
|
||||
// Checks the state and makes it valid
|
||||
const sanitizeState = state => {
|
||||
return state.withMutations(state => {
|
||||
// Remove invalid users, ensure ID match
|
||||
state.update('users', ImmutableMap(), users => (
|
||||
users.filter((user, id) => (
|
||||
validUser(user) && user.get('id') === id
|
||||
))
|
||||
));
|
||||
// Remove mismatched tokens
|
||||
state.update('tokens', ImmutableMap(), tokens => (
|
||||
tokens.filter((token, id) => (
|
||||
validId(id) && token.get('access_token') === id
|
||||
))
|
||||
));
|
||||
});
|
||||
};
|
||||
|
||||
const persistAuth = state => localStorage.setItem('soapbox:auth', JSON.stringify(state.toJS()));
|
||||
|
||||
const persistSession = state => {
|
||||
|
@ -82,6 +120,7 @@ const initialize = state => {
|
|||
maybeShiftMe(state);
|
||||
setSessionUser(state);
|
||||
migrateLegacy(state);
|
||||
sanitizeState(state);
|
||||
persistState(state);
|
||||
});
|
||||
};
|
||||
|
@ -158,6 +197,8 @@ const reducer = (state, action) => {
|
|||
return action.error.response.status === 403 ? deleteToken(state, action.token) : state;
|
||||
case SWITCH_ACCOUNT:
|
||||
return state.set('me', action.accountId);
|
||||
case ME_FETCH_SKIP:
|
||||
return state.set('me', null);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue