Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Refresh owner user/copilot Gitlab access token automatically when needed #450

Merged
merged 1 commit into from
May 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/common/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
16 changes: 10 additions & 6 deletions src/controllers/GitlabController.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -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
Expand All @@ -195,15 +197,16 @@ 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();
});

// add user to group
const gitlabUser = await GitlabService.addGroupMember(
group.groupId,
ownerUser.accessToken,
refreshedOwnerUser.accessToken,
token,
group.accessLevel,
group.expiredAt);
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion src/models/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
8 changes: 5 additions & 3 deletions src/services/GitlabService.js
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand All @@ -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({
Expand Down