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

Commit 3df66a7

Browse files
authored
Merge pull request #417 from afrisalyp/develop
Split usermapping table. Add organisation member.
2 parents 87355ab + 894f30f commit 3df66a7

14 files changed

+353
-43
lines changed

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
"lint": "gulp lint",
2323
"heroku-postbuild": "gulp build",
2424
"create-tables": "CREATE_DB=true node scripts/create-update-tables.js",
25+
"migrate-user-mapping": "node scripts/migrate-user-mapping.js",
26+
"add-organisation": "node scripts/add-organisation.js",
2527
"log-repository-collisions": "node scripts/log-repository-collisions.js"
2628
},
2729
"dependencies": {

scripts/add-organisation.js

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
const dbHelper = require('../src/common/db-helper');
2+
const helper = require('../src/common/helper');
3+
const Organisation = require('../src/models').Organisation;
4+
5+
const args = process.argv;
6+
if (args.length < 5) {
7+
console.log('Please provide data. Example: npm run add-organisation MyOrganisation ownername PAT-Token');
8+
return;
9+
}
10+
const organisationName = args[2];
11+
const owner = args[3];
12+
const pat = args[4];
13+
14+
(async () => {
15+
const dbOrganisation = await dbHelper.queryOneOrganisation(Organisation, organisationName);
16+
if (dbOrganisation) {
17+
console.log(`Updating Organisation = ${organisationName} Owner = ${owner} PAT = ${pat}.`);
18+
await dbHelper.update(Organisation, dbOrganisation.id, {
19+
name: organisationName,
20+
owner,
21+
personalAccessToken: pat
22+
});
23+
}
24+
else {
25+
console.log(`Adding Organisation = ${organisationName} Owner = ${owner} PAT = ${pat}.`);
26+
await dbHelper.create(Organisation, {
27+
id: helper.generateIdentifier(),
28+
name: organisationName,
29+
owner,
30+
personalAccessToken: pat
31+
});
32+
}
33+
})();

scripts/migrate-user-mapping.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const AWS = require('aws-sdk');
2+
const helper = require('../src/common/helper');
3+
const dbHelper = require('../src/common/db-helper');
4+
const GithubUserMapping = require('../src/models').GithubUserMapping;
5+
const GitlabUserMapping = require('../src/models').GitlabUserMapping;
6+
7+
if (process.env.IS_LOCAL) {
8+
AWS.config.update({
9+
endpoint: 'http://localhost:8000'
10+
});
11+
}
12+
var documentClient = new AWS.DynamoDB.DocumentClient();
13+
14+
(async () => {
15+
console.log('Migrating...');
16+
const params = {
17+
TableName: 'Topcoder_X.UserMapping'
18+
};
19+
20+
let items;
21+
do {
22+
items = await documentClient.scan(params).promise();
23+
items.Items.forEach(async (item) => {
24+
console.log(item);
25+
if (item.githubUserId && item.githubUsername) {
26+
await dbHelper.create(GithubUserMapping, {
27+
id: helper.generateIdentifier(),
28+
topcoderUsername: item.topcoderUsername,
29+
githubUserId: item.githubUserId,
30+
githubUsername: item.githubUsername,
31+
});
32+
}
33+
if (item.gitlabUsername && item.gitlabUserId) {
34+
await dbHelper.create(GitlabUserMapping, {
35+
id: helper.generateIdentifier(),
36+
topcoderUsername: item.topcoderUsername,
37+
gitlabUsername: item.gitlabUsername,
38+
gitlabUserId: item.gitlabUserId,
39+
});
40+
}
41+
});
42+
params.ExclusiveStartKey = items.LastEvaluatedKey;
43+
} while(typeof items.LastEvaluatedKey !== 'undefined');
44+
})();

src/common/db-helper.js

+21-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ async function queryOneUserMappingByTCUsername(model, tcusername) {
154154
model.queryOne('topcoderUsername').eq(tcusername)
155155
.all()
156156
.exec((err, result) => {
157-
if (err || !result) {
157+
if (err) {
158158
logger.debug(`queryOneUserMappingByTCUsername. Error. ${err}`);
159159
return reject(err);
160160
}
@@ -367,6 +367,25 @@ async function removeUser(Model, username, type) {
367367
});
368368
}
369369

370+
/**
371+
* Get single data by query parameters
372+
* @param {Object} model The dynamoose model to query
373+
* @param {String} organisation The organisation name
374+
* @returns {Promise<void>}
375+
*/
376+
async function queryOneOrganisation(model, organisation) {
377+
return await new Promise((resolve, reject) => {
378+
model.queryOne('name').eq(organisation)
379+
.all()
380+
.exec((err, result) => {
381+
if (err) {
382+
logger.debug(`queryOneOrganisation. Error. ${err}`);
383+
return reject(err);
384+
}
385+
return resolve(result);
386+
});
387+
});
388+
}
370389

371390
module.exports = {
372391
getById,
@@ -379,6 +398,7 @@ module.exports = {
379398
queryOneActiveCopilotPayment,
380399
queryOneActiveProject,
381400
queryOneActiveProjectWithFilter,
401+
queryOneOrganisation,
382402
queryOneIssue,
383403
queryOneUserByType,
384404
queryOneUserByTypeAndRole,

src/common/helper.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,8 @@ async function getProviderType(repoUrl) {
216216
* @returns {Object} the owner/copilot for the project
217217
*/
218218
async function getProjectCopilotOrOwner(models, project, provider, isCopilot) {
219-
const userMapping = await dbHelper.queryOneUserMappingByTCUsername(models.UserMapping,
219+
const userMapping = await dbHelper.queryOneUserMappingByTCUsername(
220+
provider === 'github' ? models.GithubUserMapping : models.GitlabUserMapping,
220221
isCopilot ? project.copilot : project.owner);
221222

222223
if (!userMapping ||

src/controllers/GithubController.js

+20-7
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const GithubService = require('../services/GithubService');
2020
const UserService = require('../services/UserService');
2121
const OwnerUserTeam = require('../models').OwnerUserTeam;
2222
const UserTeamMapping = require('../models').UserTeamMapping;
23-
const UserMapping = require('../models').UserMapping;
23+
const GithubUserMapping = require('../models').GithubUserMapping;
2424
const constants = require('../common/constants');
2525

2626
const request = superagentPromise(superagent, Promise);
@@ -127,6 +127,8 @@ async function addUserToTeam(req, res) {
127127
config.GITHUB_CLIENT_ID
128128
}&redirect_uri=${
129129
encodeURIComponent(callbackUri)
130+
}&scope=${
131+
encodeURIComponent('admin:org')
130132
}&state=${identifier}`);
131133
}
132134

@@ -156,22 +158,33 @@ async function addUserToTeamCallback(req, res) {
156158
throw new errors.UnauthorizedError('Github authorization failed.', result.body.error_description);
157159
}
158160
const token = result.body.access_token;
161+
162+
// get team details
163+
const teamDetails = await GithubService.getTeamDetails(team.ownerToken, team.teamId);
164+
const organisation = teamDetails.organization.login;
165+
166+
// Add member to organisation
167+
const addOrganisationResult = await GithubService.addOrganisationMember(organisation, token);
168+
console.log(`Add organisation member, state = ${addOrganisationResult.state}`); /* eslint-disable-line no-console */
169+
if (addOrganisationResult.state === 'pending') {
170+
const acceptInvitation = await GithubService.acceptOrganisationInvitation(organisation, token);
171+
console.log(`Accept organisation invitation by member, state = ${acceptInvitation.state}`); /* eslint-disable-line no-console */
172+
}
173+
159174
// add user to team
160175
console.log(`adding ${token} to ${team.teamId} with ${team.ownerToken}`); /* eslint-disable-line no-console */
161176
const githubUser = await GithubService.addTeamMember(team.teamId, team.ownerToken, token, team.accessLevel);
162177
// associate github username with TC username
163-
const mapping = await dbHelper.queryOneUserMappingByTCUsername(UserMapping, req.session.tcUsername);
164-
165-
// get team details
166-
const teamDetails = await GithubService.getTeamDetails(team.ownerToken, team.teamId);
178+
const mapping = await dbHelper.queryOneUserMappingByTCUsername(GithubUserMapping, req.session.tcUsername);
167179

168180
if (mapping) {
169-
await dbHelper.update(UserMapping, mapping.id, {
181+
await dbHelper.update(GithubUserMapping, mapping.id, {
170182
githubUsername: githubUser.username,
171183
githubUserId: githubUser.id,
172184
});
173185
} else {
174-
await dbHelper.create(UserMapping, {
186+
console.log('User mapping not found. Create new mapping.'); /* eslint-disable-line no-console */
187+
await dbHelper.create(GithubUserMapping, {
175188
id: helper.generateIdentifier(),
176189
topcoderUsername: req.session.tcUsername,
177190
githubUsername: githubUser.username,

src/controllers/GitlabController.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const GitlabService = require('../services/GitlabService');
2020
const UserService = require('../services/UserService');
2121
const User = require('../models').User;
2222
const OwnerUserGroup = require('../models').OwnerUserGroup;
23-
const UserMapping = require('../models').UserMapping;
23+
const GitlabUserMapping = require('../models').GitlabUserMapping;
2424
const UserGroupMapping = require('../models').UserGroupMapping;
2525

2626
const request = superagentPromise(superagent, Promise);
@@ -209,14 +209,14 @@ async function addUserToGroupCallback(req, res) {
209209
group.expiredAt);
210210
// associate gitlab username with TC username
211211

212-
const mapping = await dbHelper.queryOneUserMappingByTCUsername(UserMapping, req.session.tcUsername);
212+
const mapping = await dbHelper.queryOneUserMappingByTCUsername(GitlabUserMapping, req.session.tcUsername);
213213
if (mapping) {
214-
await dbHelper.update(UserMapping, mapping.id, {
214+
await dbHelper.update(GitlabUserMapping, mapping.id, {
215215
gitlabUsername: gitlabUser.username,
216216
gitlabUserId: gitlabUser.id,
217217
});
218218
} else {
219-
await dbHelper.create(UserMapping, {
219+
await dbHelper.create(GitlabUserMapping, {
220220
id: helper.generateIdentifier(),
221221
topcoderUsername: req.session.tcUsername,
222222
gitlabUsername: gitlabUser.username,

src/models/GithubUserMapping.js

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* This defines github user mapping model.
3+
*/
4+
'use strict';
5+
6+
const dynamoose = require('dynamoose');
7+
8+
const Schema = dynamoose.Schema;
9+
10+
const schema = new Schema({
11+
id: {
12+
type: String,
13+
required: true,
14+
hashKey: true
15+
},
16+
topcoderUsername: {
17+
type: String,
18+
required: true,
19+
index: {
20+
global: true,
21+
project: true,
22+
rangKey: 'id',
23+
name: 'TopcoderUsernameIndex'
24+
}
25+
},
26+
githubUsername: {
27+
type: String,
28+
index: {
29+
global: true,
30+
project: true,
31+
rangKey: 'id',
32+
name: 'GithubUsernameIndex'
33+
}
34+
},
35+
githubUserId: {
36+
type: Number,
37+
index: {
38+
global: true,
39+
project: true,
40+
rangKey: 'id',
41+
name: 'GithubUserIdIndex'
42+
}
43+
}
44+
});
45+
46+
module.exports = schema;

src/models/GitlabUserMapping.js

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* This defines gitlab user mapping model.
3+
*/
4+
'use strict';
5+
6+
const dynamoose = require('dynamoose');
7+
8+
const Schema = dynamoose.Schema;
9+
10+
const schema = new Schema({
11+
id: {
12+
type: String,
13+
required: true,
14+
hashKey: true
15+
},
16+
topcoderUsername: {
17+
type: String,
18+
required: true,
19+
index: {
20+
global: true,
21+
project: true,
22+
rangKey: 'id',
23+
name: 'TopcoderUsernameIndex'
24+
}
25+
},
26+
gitlabUsername: {
27+
type: String,
28+
index: {
29+
global: true,
30+
project: true,
31+
rangKey: 'id',
32+
name: 'GitlabUsernameIndex'
33+
}
34+
},
35+
gitlabUserId: {
36+
type: Number,
37+
index: {
38+
global: true,
39+
project: true,
40+
rangKey: 'id',
41+
name: 'GitlabUserIdIndex'
42+
}
43+
}
44+
});
45+
46+
module.exports = schema;
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
2-
* This defines user mapping model.
2+
* This defines organisation model.
33
*/
4+
'use strict';
5+
46
const dynamoose = require('dynamoose');
57

68
const Schema = dynamoose.Schema;
@@ -9,22 +11,26 @@ const schema = new Schema({
911
id: {
1012
type: String,
1113
required: true,
12-
hashKey: true,
14+
hashKey: true
1315
},
14-
topcoderUsername: {
16+
name: {
1517
type: String,
1618
required: true,
1719
index: {
1820
global: true,
1921
project: true,
20-
rangeKey: 'id',
21-
name: 'TopcoderUsernameIndex',
22-
},
22+
rangKey: 'id',
23+
name: 'NameIndex'
24+
}
25+
},
26+
owner: {
27+
type: String,
28+
required: true
2329
},
24-
githubUsername: String,
25-
gitlabUsername: String,
26-
githubUserId: Number,
27-
gitlabUserId: Number
30+
personalAccessToken: {
31+
type: String,
32+
required: true
33+
}
2834
});
2935

3036
module.exports = schema;

0 commit comments

Comments
 (0)