From 131b2364a8b025677816b44dc8bda26f549d73d2 Mon Sep 17 00:00:00 2001 From: gets0ul Date: Wed, 25 May 2022 19:11:42 +0700 Subject: [PATCH] Refresh owner user/copilot Gitlab access token automatically when needed --- src/common/constants.js | 6 +++--- src/controllers/GitlabController.js | 16 ++++++++++------ src/models/index.js | 2 +- src/services/GitlabService.js | 8 +++++--- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/common/constants.js b/src/common/constants.js index a1b06ed..92c41e7 100644 --- a/src/common/constants.js +++ b/src/common/constants.js @@ -43,10 +43,10 @@ const GITLAB_MAX_PER_PAGE = Number.MAX_SAFE_INTEGER; // the access level can be: 10 - GUEST, 20 - REPORTER, 30 - DEVELOPER, 40 - MASTER, 50 - OWNER const GITLAB_DEFAULT_GROUP_ACCESS_LEVEL = 30; -// The Gitlab access token default expiration in seconds -const GITLAB_ACCESS_TOKEN_DEFAULT_EXPIRATION = 3600 * 24 * 14; +// The Gitlab access token default expiration in seconds (2 hours expiration) +const GITLAB_ACCESS_TOKEN_DEFAULT_EXPIRATION = 3600 * 2; -// The Gitlab refresh token time in seconds before expiration +// The Gitlab refresh token time in seconds before expiration (5 minute before expiration) const GITLAB_REFRESH_TOKEN_BEFORE_EXPIRATION = 300; const GITHUB_OWNER_CALLBACK_URL = '/api/v1/github/owneruser/callback'; diff --git a/src/controllers/GitlabController.js b/src/controllers/GitlabController.js index 8eba050..5434b11 100644 --- a/src/controllers/GitlabController.js +++ b/src/controllers/GitlabController.js @@ -102,7 +102,9 @@ async function listOwnerUserGroups(req) { if (!user || !user.accessToken) { throw new errors.UnauthorizedError('You have not setup for Gitlab.'); } - return await GitlabService.listOwnerUserGroups(user.accessToken, req.query.page, req.query.perPage, req.query.getAll); + const refreshedUser = await GitlabService.refreshGitlabUserAccessToken(user); + return await GitlabService.listOwnerUserGroups(refreshedUser.accessToken, req.query.page, + req.query.perPage, req.query.getAll); } /** @@ -175,7 +177,7 @@ async function addUserToGroupCallback(req, res) { throw new errors.NotFoundError('The owner user is not found or not accessible.'); } - await GitlabService.refreshGitlabUserAccessToken(ownerUser); + const refreshedOwnerUser = await GitlabService.refreshGitlabUserAccessToken(ownerUser); // exchange code to get normal user token const result = await request @@ -195,7 +197,8 @@ async function addUserToGroupCallback(req, res) { const token = result.body.access_token; // get group name - const groupsResult = await GitlabService.listOwnerUserGroups(ownerUser.accessToken, 1, constants.MAX_PER_PAGE, true); + const groupsResult = await GitlabService.listOwnerUserGroups(refreshedOwnerUser.accessToken, 1, + constants.MAX_PER_PAGE, true); const currentGroup = _.find(groupsResult.groups, (item) => { // eslint-disable-line arrow-body-style return item.id.toString() === group.groupId.toString(); }); @@ -203,7 +206,7 @@ async function addUserToGroupCallback(req, res) { // add user to group const gitlabUser = await GitlabService.addGroupMember( group.groupId, - ownerUser.accessToken, + refreshedOwnerUser.accessToken, token, group.accessLevel, group.expiredAt); @@ -265,11 +268,12 @@ async function deleteUsersFromTeam(req, res) { if (!ownerUser) { throw new errors.NotFoundError('The owner user is not found or not accessible.'); } - await GitlabService.refreshGitlabUserAccessToken(ownerUser); + const refreshedOwnerUser = await GitlabService.refreshGitlabUserAccessToken(ownerUser); const userGroupMappings = await dbHelper.scan(UserGroupMapping, {groupId}); // eslint-disable-next-line no-restricted-syntax for (const userGroupMapItem of userGroupMappings) { - await GitlabService.deleteUserFromGitlabGroup(ownerUser.accessToken, groupId, userGroupMapItem.gitlabUserId); + await GitlabService.deleteUserFromGitlabGroup(refreshedOwnerUser.accessToken, groupId, + userGroupMapItem.gitlabUserId); await dbHelper.removeById(UserGroupMapping, userGroupMapItem.id); } } catch (err) { diff --git a/src/models/index.js b/src/models/index.js index 8038663..f05e709 100644 --- a/src/models/index.js +++ b/src/models/index.js @@ -18,7 +18,7 @@ if (config.DYNAMODB.AWS_ACCESS_KEY_ID) { dynamoose.AWS.config.update(dynamooseConfig); if (config.DYNAMODB.IS_LOCAL === 'true') { - dynamoose.local(); + dynamoose.local(config.DYNAMODB.URL); } dynamoose.setDefaults({ diff --git a/src/services/GitlabService.js b/src/services/GitlabService.js index 4144407..eec3086 100644 --- a/src/services/GitlabService.js +++ b/src/services/GitlabService.js @@ -262,10 +262,11 @@ getUserIdByUsername.schema = Joi.object().keys({ /** * Refresh the owner user access token if needed * @param {Object} gitlabOwner the gitlab owner + * @returns {Promise} the promise result of owner user with refreshed token */ async function refreshGitlabUserAccessToken(gitlabOwner) { - if (gitlabOwner.accessTokenExpiration && gitlabOwner.accessTokenExpiration.getTime() <= - new Date().getTime() + constants.GITLAB_REFRESH_TOKEN_BEFORE_EXPIRATION * MS_PER_SECOND) { + if (gitlabOwner.accessTokenExpiration && new Date().getTime() > gitlabOwner.accessTokenExpiration.getTime() - + (constants.GITLAB_REFRESH_TOKEN_BEFORE_EXPIRATION * MS_PER_SECOND)) { const refreshTokenResult = await request .post('https://gitlab.com/oauth/token') .query({ @@ -278,12 +279,13 @@ async function refreshGitlabUserAccessToken(gitlabOwner) { .end(); // save user token data const expiresIn = refreshTokenResult.body.expires_in || constants.GITLAB_ACCESS_TOKEN_DEFAULT_EXPIRATION; - await dbHelper.update(User, gitlabOwner.id, { + return await dbHelper.update(User, gitlabOwner.id, { accessToken: refreshTokenResult.body.access_token, accessTokenExpiration: new Date(new Date().getTime() + expiresIn * MS_PER_SECOND), refreshToken: refreshTokenResult.body.refresh_token, }); } + return gitlabOwner; } refreshGitlabUserAccessToken.schema = Joi.object().keys({