From 67baf4a840032203ca1a0fc87f911f3369790cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillermo=20Vay=C3=A1?= Date: Thu, 4 Jul 2019 11:55:38 +0200 Subject: [PATCH] [MM-7854] revoke sessions for all users redux (#866) * [MM-7854] revoke sessions for all users redux * [MM-7854] fix routes to match server * [MM-7854] remove userid from revoke action --- src/action_types/users.js | 1 + src/actions/users.js | 18 ++++++++++++ src/actions/users.test.js | 53 ++++++++++++++++++++++++++++++++++ src/client/client4.js | 7 +++++ src/reducers/entities/users.js | 3 ++ 5 files changed, 82 insertions(+) diff --git a/src/action_types/users.js b/src/action_types/users.js index 48e3117be..7666237a9 100644 --- a/src/action_types/users.js +++ b/src/action_types/users.js @@ -18,6 +18,7 @@ export default keyMirror({ LOGOUT_FAILURE: null, REVOKE_ALL_USER_SESSIONS_SUCCESS: null, + REVOKE_SESSIONS_FOR_ALL_USERS_SUCCESS: null, CHECK_MFA_REQUEST: null, CHECK_MFA_SUCCESS: null, diff --git a/src/actions/users.js b/src/actions/users.js index 959ca587a..178bc02d3 100644 --- a/src/actions/users.js +++ b/src/actions/users.js @@ -769,6 +769,23 @@ export function revokeAllSessionsForUser(userId: string): ActionFunc { }; } +export function revokeSessionsForAllUsers(): ActionFunc { + return async (dispatch: DispatchFunc, getState: GetStateFunc) => { + try { + await Client4.revokeSessionsForAllUsers(); + } catch (error) { + forceLogoutIfNecessary(error, dispatch, getState); + dispatch(logError(error)); + return {error}; + } + dispatch({ + type: UserTypes.REVOKE_SESSIONS_FOR_ALL_USERS_SUCCESS, + data: null, + }); + return {data: true}; + }; +} + export function loadProfilesForDirect(): ActionFunc { return async (dispatch: DispatchFunc, getState: GetStateFunc) => { const state = getState(); @@ -1432,6 +1449,7 @@ export default { loadProfilesForDirect, revokeSession, revokeAllSessionsForUser, + revokeSessionsForAllUsers, getUserAudits, searchProfiles, startPeriodicStatusUpdates, diff --git a/src/actions/users.test.js b/src/actions/users.test.js index b82c832ba..cf170c0fd 100644 --- a/src/actions/users.test.js +++ b/src/actions/users.test.js @@ -666,6 +666,59 @@ describe('Actions.Users', () => { await TestHelper.basicClient4.login(TestHelper.basicUser.email, 'password1'); }); + it('revokeSessionsForAllUsers', async () => { + const user = TestHelper.basicUser; + nock(Client4.getUsersRoute()). + post('/logout'). + reply(200, OK_RESPONSE); + await TestHelper.basicClient4.logout(); + let sessions = store.getState().entities.users.mySessions; + + assert.strictEqual(sessions.length, 0); + + TestHelper.mockLogin(); + await Actions.loginById(user.id, 'password1')(store.dispatch, store.getState); + + nock(Client4.getUsersRoute()). + post('/login'). + reply(200, TestHelper.basicUser); + await TestHelper.basicClient4.login(TestHelper.basicUser.email, 'password1'); + + nock(Client4.getBaseRoute()). + get(`/users/${user.id}/sessions`). + reply(200, [{id: TestHelper.generateId(), create_at: 1507756921338, expires_at: 1510348921338, last_activity_at: 1507821125630, user_id: TestHelper.basicUser.id, device_id: '', roles: 'system_admin system_user'}, {id: TestHelper.generateId(), create_at: 1507756921338, expires_at: 1510348921338, last_activity_at: 1507821125630, user_id: TestHelper.basicUser.id, device_id: '', roles: 'system_admin system_user'}]); + await Actions.getSessions(user.id)(store.dispatch, store.getState); + + sessions = store.getState().entities.users.mySessions; + assert.ok(sessions.length > 1); + + nock(Client4.getBaseRoute()). + post('/users/sessions/revoke/all'). + reply(200, OK_RESPONSE); + const {data} = await Actions.revokeSessionsForAllUsers(user.id)(store.dispatch, store.getState); + assert.deepEqual(data, true); + + nock(Client4.getUsersRoute()). + get(''). + query(true). + reply(401, {}); + await Actions.getProfiles(0)(store.dispatch, store.getState); + + const logoutRequest = store.getState().requests.users.logout; + if (logoutRequest.status === RequestStatus.FAILURE) { + throw new Error(JSON.stringify(logoutRequest.error)); + } + + sessions = store.getState().entities.users.mySessions; + + assert.strictEqual(sessions.length, 0); + + nock(Client4.getUsersRoute()). + post('/login'). + reply(200, TestHelper.basicUser); + await TestHelper.basicClient4.login(TestHelper.basicUser.email, 'password1'); + }); + it('getUserAudits', async () => { nock(Client4.getUsersRoute()). get(`/${TestHelper.basicUser.id}/audits`). diff --git a/src/client/client4.js b/src/client/client4.js index 45f1efcdb..fb017a773 100644 --- a/src/client/client4.js +++ b/src/client/client4.js @@ -701,6 +701,13 @@ export default class Client4 { ); }; + revokeSessionsForAllUsers = async () => { + return this.doFetch( + `${this.getUsersRoute()}/sessions/revoke/all`, + {method: 'post'} + ); + }; + getUserAudits = async (userId, page = 0, perPage = PER_PAGE_DEFAULT) => { return this.doFetch( `${this.getUserRoute(userId)}/audits${buildQueryString({page, per_page: perPage})}`, diff --git a/src/reducers/entities/users.js b/src/reducers/entities/users.js index b69e1f6ac..927c589ce 100644 --- a/src/reducers/entities/users.js +++ b/src/reducers/entities/users.js @@ -114,6 +114,9 @@ function mySessions(state = [], action) { } return state; + case UserTypes.REVOKE_SESSIONS_FOR_ALL_USERS_SUCCESS: + return []; + case UserTypes.LOGOUT_SUCCESS: return [];