diff --git a/test/api/v3/integration/user/auth/POST-login-local.test.js b/test/api/v3/integration/user/auth/POST-login-local.test.js index a9ba3e74c1..1b6776ad88 100644 --- a/test/api/v3/integration/user/auth/POST-login-local.test.js +++ b/test/api/v3/integration/user/auth/POST-login-local.test.js @@ -110,6 +110,18 @@ describe('POST /user/auth/local/login', () => { expect(isValidPassword).to.equal(true); }); + it('sets auth.timestamps.updated', async () => { + const oldUpdated = new Date(user.auth.timestamps.updated); + // login + await api.post(endpoint, { + username: user.auth.local.email, + password, + }); + + await user.sync(); + expect(user.auth.timestamps.updated).to.be.greaterThan(oldUpdated); + }); + it('user uses social authentication and has no password', async () => { await user.unset({ 'auth.local.hashed_password': 1, diff --git a/test/api/v3/integration/user/auth/POST-user_auth_social.test.js b/test/api/v3/integration/user/auth/POST-user_auth_social.test.js index df976d0987..85792e98a1 100644 --- a/test/api/v3/integration/user/auth/POST-user_auth_social.test.js +++ b/test/api/v3/integration/user/auth/POST-user_auth_social.test.js @@ -167,5 +167,24 @@ describe('POST /user/auth/social', () => { await expect(getProperty('users', user._id, '_ABtests')).to.eventually.be.a('object'); }); + + it('sets auth.timestamps.updated', async () => { + let oldUpdated = new Date(user.auth.timestamps.updated); + await user.post(endpoint, { + authResponse: { access_token: randomAccessToken }, // eslint-disable-line camelcase + network, + }); + await user.sync(); + expect(user.auth.timestamps.updated).to.be.greaterThan(oldUpdated); + oldUpdated = new Date(user.auth.timestamps.updated); + + // Do it again to ensure it updates even when nothing else changes + await api.post(endpoint, { + authResponse: { access_token: randomAccessToken }, // eslint-disable-line camelcase + network, + }); + await user.sync(); + expect(user.auth.timestamps.updated).to.be.greaterThan(oldUpdated); + }); }); }); diff --git a/website/server/controllers/api-v3/auth.js b/website/server/controllers/api-v3/auth.js index d8359beaba..e5c091b5de 100644 --- a/website/server/controllers/api-v3/auth.js +++ b/website/server/controllers/api-v3/auth.js @@ -121,8 +121,10 @@ api.loginLocal = { // convert the hashed password to bcrypt from sha1 if (user.auth.local.passwordHashMethod === 'sha1') { await passwordUtils.convertToBcrypt(user, password); - await user.save(); } + // Force the updated timestamp to update, so that we know they logged in + user.auth.timestamps.updated = new Date(); + await user.save(); res.analytics.track('login', { category: 'behaviour', diff --git a/website/server/libs/auth/social.js b/website/server/libs/auth/social.js index e17b85b23d..c5d3ff10e8 100644 --- a/website/server/libs/auth/social.js +++ b/website/server/libs/auth/social.js @@ -67,10 +67,10 @@ export async function loginSocial (req, res) { // eslint-disable-line import/pre } if (!user.auth.local.email) { user.auth.local.email = await socialEmailToLocal(user); - if (user.auth.local.email) { - await user.save(); - } } + // Force the updated timestampt to update, so that we know they logged in + user.auth.timestamps.updated = new Date(); + await user.save(); return loginRes(user, req, res); }