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,
|
VERIFY_CREDENTIALS_FAIL,
|
||||||
SWITCH_ACCOUNT,
|
SWITCH_ACCOUNT,
|
||||||
} from 'soapbox/actions/auth';
|
} from 'soapbox/actions/auth';
|
||||||
|
import { ME_FETCH_SKIP } from 'soapbox/actions/me';
|
||||||
|
|
||||||
describe('auth reducer', () => {
|
describe('auth reducer', () => {
|
||||||
it('should return the initial state', () => {
|
it('should return the initial state', () => {
|
||||||
|
@ -250,4 +251,13 @@ describe('auth reducer', () => {
|
||||||
expect(result.get('me')).toEqual('5678');
|
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_SUCCESS,
|
||||||
VERIFY_CREDENTIALS_FAIL,
|
VERIFY_CREDENTIALS_FAIL,
|
||||||
} from '../actions/auth';
|
} 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({
|
const defaultState = ImmutableMap({
|
||||||
app: ImmutableMap(),
|
app: ImmutableMap(),
|
||||||
|
@ -16,31 +17,50 @@ const defaultState = ImmutableMap({
|
||||||
me: null,
|
me: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const validId = id => typeof id === 'string' && id !== 'null' && id !== 'undefined';
|
||||||
|
|
||||||
const getSessionUser = () => {
|
const getSessionUser = () => {
|
||||||
const id = sessionStorage.getItem('soapbox:auth:me');
|
const id = sessionStorage.getItem('soapbox:auth:me');
|
||||||
if (id && typeof id === 'string' && id !== 'null' && id !== 'undefined') {
|
return validId(id) ? id : undefined;
|
||||||
return id;
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const sessionUser = getSessionUser();
|
const sessionUser = getSessionUser();
|
||||||
const localState = fromJS(JSON.parse(localStorage.getItem('soapbox:auth')));
|
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.
|
// If `me` doesn't match an existing user, attempt to shift it.
|
||||||
const maybeShiftMe = state => {
|
const maybeShiftMe = state => {
|
||||||
const users = state.get('users', ImmutableMap());
|
const users = state.get('users', ImmutableMap());
|
||||||
const me = state.get('me');
|
const me = state.get('me');
|
||||||
|
|
||||||
if (!users.get(me)) {
|
if (!validUser(users.get(me))) {
|
||||||
return state.set('me', users.first(ImmutableMap()).get('id', null));
|
const nextUser = firstValidUser(state);
|
||||||
|
return state.set('me', nextUser ? nextUser.get('id') : null);
|
||||||
} else {
|
} else {
|
||||||
return state;
|
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
|
// Upgrade the initial state
|
||||||
const migrateLegacy = 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 persistAuth = state => localStorage.setItem('soapbox:auth', JSON.stringify(state.toJS()));
|
||||||
|
|
||||||
const persistSession = state => {
|
const persistSession = state => {
|
||||||
|
@ -82,6 +120,7 @@ const initialize = state => {
|
||||||
maybeShiftMe(state);
|
maybeShiftMe(state);
|
||||||
setSessionUser(state);
|
setSessionUser(state);
|
||||||
migrateLegacy(state);
|
migrateLegacy(state);
|
||||||
|
sanitizeState(state);
|
||||||
persistState(state);
|
persistState(state);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -158,6 +197,8 @@ const reducer = (state, action) => {
|
||||||
return action.error.response.status === 403 ? deleteToken(state, action.token) : state;
|
return action.error.response.status === 403 ? deleteToken(state, action.token) : state;
|
||||||
case SWITCH_ACCOUNT:
|
case SWITCH_ACCOUNT:
|
||||||
return state.set('me', action.accountId);
|
return state.set('me', action.accountId);
|
||||||
|
case ME_FETCH_SKIP:
|
||||||
|
return state.set('me', null);
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue