From f0f5a25c03c32e61380b3c671a14c118199daeaa Mon Sep 17 00:00:00 2001 From: rpletz Date: Fri, 17 Nov 2023 11:01:04 -0800 Subject: [PATCH] Add lastloginat to user --- app/middleware/acl.js | 10 ++++++++++ app/models/user/user.js | 6 ++++++ ...231117185810-DEVSU-2128-add-lastloginat.js | 20 +++++++++++++++++++ test/routes/user/user.test.js | 17 ++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 migrations/20231117185810-DEVSU-2128-add-lastloginat.js diff --git a/app/middleware/acl.js b/app/middleware/acl.js index c49250772..e833fee0a 100644 --- a/app/middleware/acl.js +++ b/app/middleware/acl.js @@ -52,6 +52,16 @@ const SPECIAL_CASES = [ ]; module.exports = async (req, res, next) => { + // Update last time the user logged in, limit to once a day + const currentDate = new Date().toDateString(); + const userLastLogin = req.user.lastLoginAt + ? new Date(req.user.lastLoginAt).toDateString() + : ''; + + if (userLastLogin !== currentDate) { + await req.user.update({lastLoginAt: new Date()}); + } + // Check if user is an admin if (isAdmin(req.user)) { return next(); diff --git a/app/models/user/user.js b/app/models/user/user.js index c0d919ba0..f3c6a71db 100644 --- a/app/models/user/user.js +++ b/app/models/user/user.js @@ -44,6 +44,12 @@ module.exports = (sequelize, Sq) => { schema: {type: 'string', format: 'email'}, }, }, + lastLoginAt: { + name: 'lastLoginAt', + field: 'last_login_at', + type: Sq.DATE, + defaultValue: null, + }, }, { ...DEFAULT_OPTIONS, indexes: [ diff --git a/migrations/20231117185810-DEVSU-2128-add-lastloginat.js b/migrations/20231117185810-DEVSU-2128-add-lastloginat.js new file mode 100644 index 000000000..1b91a3885 --- /dev/null +++ b/migrations/20231117185810-DEVSU-2128-add-lastloginat.js @@ -0,0 +1,20 @@ +const TABLE = 'users'; + +module.exports = { + up: async (queryInterface, Sq) => { + return queryInterface.sequelize.transaction(async (transaction) => { + await queryInterface.addColumn( + TABLE, + 'last_login_at', + { + type: Sq.DATE, + }, + {transaction}, + ); + }); + }, + + down: async () => { + throw new Error('Not Implemented!'); + }, +}; diff --git a/test/routes/user/user.test.js b/test/routes/user/user.test.js index 7c7eb8632..84673061e 100644 --- a/test/routes/user/user.test.js +++ b/test/routes/user/user.test.js @@ -96,6 +96,23 @@ describe('/user', () => { checkUser(res.body); }); + // Test that lastLoginAt is updated with a new request + test('/me - test if requests upload last_login_at 200 Success', async () => { + const res = await request + .get('/api/user/me') + .auth(username, password) + .type('json') + .expect(HTTP_STATUS.OK); + + const loginDate = new Date(res.body.lastLoginAt); + const currentDate = new Date(); + + checkUser(res.body); + expect( + loginDate.toDateString() === currentDate.toDateString(), + ).toBe(true); + }); + // Test for GET /user/search 200 endpoint test('/search - 200 Success', async () => { // Create unique first name