diff --git a/app/soapbox/reducers/__tests__/auth-test.js b/app/soapbox/reducers/__tests__/auth-test.js index 42bae3bf0..4adce1eae 100644 --- a/app/soapbox/reducers/__tests__/auth-test.js +++ b/app/soapbox/reducers/__tests__/auth-test.js @@ -18,6 +18,22 @@ describe('auth reducer', () => { })); }); + describe('@@INIT', () => { + it('sets `me` to the next available user if blank', () => { + const state = fromJS({ + me: null, + users: { + '1234': { id: '1234', access_token: 'ABCDEFG' }, + '5678': { id: '5678', access_token: 'HIJKLMN' }, + }, + }); + + const action = { type: '@@INIT' }; + const result = reducer(state, action); + expect(result.get('me')).toEqual('1234'); + }); + }); + describe('AUTH_APP_CREATED', () => { it('should copy in the app', () => { const token = { token_type: 'Bearer', access_token: 'ABCDEFG' }; diff --git a/app/soapbox/reducers/auth.js b/app/soapbox/reducers/auth.js index 671ef0d0a..c0b0ffe09 100644 --- a/app/soapbox/reducers/auth.js +++ b/app/soapbox/reducers/auth.js @@ -31,6 +31,7 @@ const importCredentials = (state, token, account) => { })); state.setIn(['tokens', token, 'account'], account.id); state.update('me', null, me => me || account.id); + upgradeLegacyId(state, account); }); }; @@ -54,8 +55,48 @@ const importFailedToken = (state, token) => { }); }; +// Upgrade the initial state +const migrateLegacy = state => { + if (localState) return state; + return state.withMutations(state => { + const app = fromJS(JSON.parse(localStorage.getItem('soapbox:auth:app'))); + const user = fromJS(JSON.parse(localStorage.getItem('soapbox:auth:user'))); + state.set('me', '_legacy'); // Placeholder account ID + state.set('app', app); + state.set('tokens', ImmutableMap({ + [user.get('access_token')]: user.set('account', '_legacy'), + })); + state.set('users', ImmutableMap({ + '_legacy': ImmutableMap({ + id: '_legacy', + access_token: user.get('access_token'), + }), + })); + }); +}; + +// Upgrade the `_legacy` placeholder ID with a real account +const upgradeLegacyId = (state, account) => { + if (localState) return state; + return state.withMutations(state => { + state.update('me', null, me => me === '_legacy' ? account.id : me); + state.deleteIn(['users', '_legacy']); + }); + // TODO: Delete `soapbox:auth:app` and `soapbox:auth:user` localStorage? + // By this point it's probably safe, but we'll leave it just in case. +}; + +const initialize = state => { + return state.withMutations(state => { + maybeShiftMe(state); + migrateLegacy(state); + }); +}; + const reducer = (state, action) => { switch(action.type) { + case '@@INIT': + return initialize(state); case AUTH_APP_CREATED: return state.set('app', fromJS(action.app)); case AUTH_APP_AUTHORIZED: