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

Commit c079605

Browse files
authored
Merge pull request #20 from veshu/develop
changes for #17 #15 #16
2 parents 5cc51b5 + f67cba7 commit c079605

File tree

9 files changed

+490
-170
lines changed

9 files changed

+490
-170
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ Note: heroku domain should match subdomain of topcoder-dev or topcoder depending
7373

7474
## Verification
7575

76-
- run `npm serve` to start the app
76+
- run `npm run serve` to start the app
7777
- go to topcoderx.topcoder-dev.com and it will redirect to Topcoder login page, after successful login it will redirect back to Topcoder x app.
7878
- go to settings by clicking username at top right corner
7979
- setup both git provider to authorize topcoder-x to manage your repo on behalf of you

package-lock.json

Lines changed: 337 additions & 30 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"mongoose": "^4.11.9",
7171
"octonode": "^0.9.2",
7272
"pace-js": "~1.0.2",
73+
"parse-domain": "^2.1.2",
7374
"shortid": "^2.2.8",
7475
"superagent": "^3.6.0",
7576
"superagent-promise": "^1.1.0",

src/common/helper.js

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@ const getParams = require('get-parameter-names');
1515
const bluebird = require('bluebird');
1616
const uuid = require('uuid/v4');
1717
const bcrypt = require('bcryptjs');
18+
const parseDomain = require('parse-domain');
1819
const config = require('../config');
1920
const logger = require('./logger');
2021
const errors = require('./errors');
2122
const constants = require('./constants');
2223
const NotFoundError = require('./errors').NotFoundError;
24+
const ValidationError = require('./errors').ValidationError;
2325

2426
bluebird.promisifyAll(bcrypt);
27+
bluebird.promisifyAll(parseDomain);
2528

2629
/**
2730
* Convert array with arguments to object
@@ -82,7 +85,7 @@ function _decorateWithValidators(service) {
8285
const params = getParams(method);
8386
service[name] = async function serviceMethodWithValidation(...args) {
8487
const value = _combineObject(params, args);
85-
const normalized = Joi.attempt(value, method.schema, {abortEarly: false});
88+
const normalized = Joi.attempt(value, method.schema, { abortEarly: false });
8689
// Joi will normalize values
8790
// for example string number '1' to 1
8891
// if schema type is number
@@ -188,6 +191,42 @@ async function ensureExists(Model, criteria) {
188191
return result;
189192
}
190193

194+
/**
195+
* get the provider name from git repo url
196+
* @param {String} repoUrl the project repo URL
197+
* @returns {String} the provider
198+
*/
199+
async function getProviderType(repoUrl) {
200+
const parsedDomain = await parseDomain(repoUrl);
201+
if (!parsedDomain || !parsedDomain.domain || (parsedDomain.domain !== 'github' && parsedDomain.domain !== 'gitlab')) {
202+
throw new ValidationError('Invalid git repo url');
203+
}
204+
return parsedDomain.domain;
205+
}
206+
207+
/**
208+
* gets the git username of copilot for a project
209+
* @param {Object} models the db models
210+
* @param {Object} project the db project detail
211+
* @param {String} provider the git provider
212+
* @returns {Object} the owner/copilot for the project
213+
*/
214+
async function getProjectOwner(models, project, provider) {
215+
const userMapping = await models.UserMapping.findOne({
216+
topcoderUsername: project.username,
217+
});
218+
219+
if (!userMapping || (provider === 'github' && !userMapping.githubUserId) || (provider === 'gitlab' && !userMapping.gitlabUserId)) {
220+
throw new Error(`Couldn't find owner username for '${provider}' for this repository.`);
221+
}
222+
223+
const copilot = await models.User.findOne({
224+
username: provider === 'github' ? userMapping.githubUsername : userMapping.gitlabUsername,
225+
type: provider,
226+
});
227+
return copilot;
228+
}
229+
191230

192231
/**
193232
* Generate an unique identifier
@@ -206,4 +245,6 @@ module.exports = {
206245
convertGitLabError,
207246
ensureExists,
208247
generateIdentifier,
248+
getProviderType,
249+
getProjectOwner,
209250
};

src/controllers/ProjectController.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const ProjectService = require('../services/ProjectService');
1818
* @returns {Object} the result
1919
*/
2020
async function create(req) {
21-
return await ProjectService.create(req.body);
21+
return await ProjectService.create(req.body, req.currentUser.handle);
2222
}
2323

2424
/**
@@ -28,7 +28,7 @@ async function create(req) {
2828
* @returns {Object} the result
2929
*/
3030
async function update(req) {
31-
return await ProjectService.update(req.body);
31+
return await ProjectService.update(req.body, req.currentUser.handle);
3232
}
3333

3434
/**
@@ -37,7 +37,7 @@ async function update(req) {
3737
* @returns {Array} the result
3838
*/
3939
async function getAll(req) {
40-
return await ProjectService.getAll(req.query.status);
40+
return await ProjectService.getAll(req.query.status, req.currentUser.handle);
4141
}
4242

4343
/**
@@ -47,7 +47,7 @@ async function getAll(req) {
4747
* @returns {Object} the result
4848
*/
4949
async function createLabel(req) {
50-
return await ProjectService.createLabel(req.body);
50+
return await ProjectService.createLabel(req.body, req.currentUser.handle);
5151
}
5252

5353
/**
@@ -57,7 +57,7 @@ async function createLabel(req) {
5757
* @returns {Object} the result
5858
*/
5959
async function createHook(req) {
60-
return await ProjectService.createHook(req.body);
60+
return await ProjectService.createHook(req.body, req.currentUser.handle);
6161
}
6262

6363
module.exports = {

src/front/src/.eslintrc

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
"rules": {
66
"angular/no-service-method": 0,
77
"angular/window-service": 0,
8-
"angular/di": [2, "array"],
8+
"angular/di": [
9+
2,
10+
"array"
11+
],
912
"angular/angularelement": 0,
1013
"angular/timeout-service": 0,
1114
"max-params": 0,
@@ -14,24 +17,26 @@
1417
"valid-jsdoc": 0,
1518
"require-jsdoc": 0,
1619
"no-magic-numbers": 0,
17-
"no-invalid-this" : 0,
18-
"no-nested-ternary" : 0,
19-
"no-void" : 0,
20-
"consistent-return" : 0,
21-
"lodash/prefer-includes" : 0,
22-
"one-var" : 0,
23-
"no-restricted-syntax" : 0,
24-
"func-style" : 0,
25-
"vars-on-top" : 0,
26-
"func-names" : 0,
27-
"prefer-rest-params" : 0,
28-
"no-var":0,
29-
"no-inner-declarations":0
20+
"no-invalid-this": 0,
21+
"no-nested-ternary": 0,
22+
"no-void": 0,
23+
"consistent-return": 0,
24+
"lodash/prefer-includes": 0,
25+
"one-var": 0,
26+
"no-restricted-syntax": 0,
27+
"func-style": 0,
28+
"vars-on-top": 0,
29+
"func-names": 0,
30+
"prefer-rest-params": 0,
31+
"no-var": 0,
32+
"no-inner-declarations": 0,
33+
"prefer-arrow-callback": 0,
34+
"prefer-template":0,
3035
},
3136
"env": {
3237
"browser": true,
3338
"commonjs": true,
3439
"es6": true,
3540
"jquery": true
3641
}
37-
}
42+
}

src/front/src/app/projects/projects.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ <h4>You don't have active projects right now. Please
4242
</tr>
4343
</thead>
4444
<tbody>
45-
<tr ng-repeat="project in projects" class="animate-repeat" ng-class-even="'footable-even'" ng-class-odd="'footable-odd'">
45+
<tr ng-repeat="project in projects" ng-class-even="'footable-even'" ng-class-odd="'footable-odd'">
4646
<td class="col-lg-2">{{project.title}}</td>
4747
<td class="col-lg-2">
4848
<a href="{{directUrlBase}}{{project.tcDirectId}}" target="_blank">{{project.tcDirectId}}</a>

src/front/src/app/upsertproject/upsertproject.controller.js

Lines changed: 21 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,20 @@
88
angular.module('topcoderX').controller('ProjectController', ['currentUser', '$scope', '$timeout', 'ProjectService',
99
'$rootScope', '$state', 'Alert', function (currentUser, $scope, $timeout, ProjectService, $rootScope, $state, Alert) {
1010

11-
//Maintain the navigation state.
11+
// Maintain the navigation state.
1212
$timeout(function () {
1313
angular.element('#projectsManagement').addClass('active');
1414
}, 0);
1515

16-
//below logic is trying to identify whether we are editing a project
16+
// below logic is trying to identify whether we are editing a project
1717
$scope.editing = true;
1818
$scope.project = {
19-
'title': '',
20-
'tcDirectId': '',
21-
'repoUrl': '',
22-
'rocketChatWebhook': null,
23-
'rocketChatChannelName': null,
24-
'archived': false
19+
title: '',
20+
tcDirectId: '',
21+
repoUrl: '',
22+
rocketChatWebhook: null,
23+
rocketChatChannelName: null,
24+
archived: false,
2525
};
2626
if ($rootScope.project) {
2727
$scope.title = 'Edit a Project';
@@ -33,97 +33,40 @@ angular.module('topcoderX').controller('ProjectController', ['currentUser', '$sc
3333
$scope.editing = false;
3434
}
3535

36-
//represents the repo owner
37-
$scope.repoOwner = '';
38-
39-
//represents the repo name
40-
$scope.repoName = '';
41-
42-
//represents the repo is located at github or gitlab
43-
$scope.repoType = '';
44-
45-
//function to get the repo's owner and the repo's name based on repoUrl
46-
const getRepoDetail = function (repoUrl, callback, errorCallBack) {
47-
$scope.$broadcast('alert.ClearAll', {});
48-
if (repoUrl.endsWith('/')) {
49-
repoUrl = repoUrl.slice(0, -1);
50-
}
51-
const results = repoUrl.split('/');
52-
$scope.repoName = results[results.length - 1];
53-
$scope.repoOwner = results[results.length - 2];
54-
$scope.repoType = results[results.length - 3].split('.')[0];
55-
ProjectService.getUserToken($scope.repoOwner, $scope.repoType).then(function (response) {
56-
if (angular.isDefined(response.data.token)) {
57-
$scope.token = response.data.token;
58-
return callback();
59-
} else {
60-
const erroMessage = 'Token not found for the user ' + $scope.repoOwner + ' of type ' + $scope.repoType + ' please complete profile setting';
61-
Alert.error(erroMessage, $scope);
62-
}
63-
}, function (error) {
64-
errorCallBack(error);
65-
});
66-
};
67-
68-
//function to add labels to the current project.
36+
// function to add labels to the current project.
6937
$scope.addLabels = function () {
70-
getRepoDetail($scope.project.repoUrl, function () {
71-
// for (var i = 0; i < $rootScope.config.LABELS.length; i++) {
72-
var objc = {
73-
'repoOwner': $scope.repoOwner,
74-
'repoName': $scope.repoName,
75-
'repoToken': $scope.token,
76-
77-
'repoType': $scope.repoType
78-
};
79-
ProjectService.createLabel(objc).then(function () {
80-
Alert.info('Label Added Successfully', $scope);
81-
}).catch(function (error) {
82-
Alert.error(error.data.message, $scope);
83-
});
84-
// }
85-
}, function (error) {
38+
ProjectService.createLabel({ projectId: $scope.project.id }).then(function () {
39+
Alert.info('Label Added Successfully', $scope);
40+
}).catch(function (error) {
8641
Alert.error(error.data.message, $scope);
8742
});
8843
};
8944

90-
//function to add hooks to the current project.
45+
// function to add hooks to the current project.
9146
$scope.addHooks = function () {
92-
getRepoDetail($scope.project.repoUrl, function () {
93-
var objc = {
94-
'repoOwner': $scope.repoOwner,
95-
'repoName': $scope.repoName,
96-
'repoToken': $scope.token,
97-
'repoType': $scope.repoType,
98-
'projectId': $scope.project.id
99-
};
100-
ProjectService.createHooks(objc).then(function () {
101-
Alert.info('Webhook Added Successfully', $scope);
102-
}).catch(function (error) {
103-
Alert.error(error.data.message, $scope);
104-
});
105-
}, function (error) {
47+
ProjectService.createHooks({ projectId: $scope.project.id }).then(function () {
48+
Alert.info('Webhook Added Successfully', $scope);
49+
}).catch(function (error) {
10650
Alert.error(error.data.message, $scope);
10751
});
10852
};
10953

110-
//save the project info to database, and go back to project list view.
54+
// save the project info to database, and go back to project list view.
11155
$scope.save = function () {
112-
$scope.project.username = $rootScope.currentUser.handle;
11356
if ($scope.editing) {
11457
ProjectService.update($scope.project).then(function () {
11558
Alert.info('Project Updated Successfully', $scope);
11659
$state.go('app.projects');
117-
}).catch((function (error) {
60+
}).catch(function (error) {
11861
Alert.error(error.data.message, $scope);
119-
}))
62+
});
12063
} else {
12164
ProjectService.create($scope.project).then(function () {
12265
Alert.info('Project Created Successfully', $scope);
12366
$state.go('app.projects');
12467
}).catch(function (error) {
12568
Alert.error(error.data.message, $scope);
126-
})
69+
});
12770
}
128-
}
71+
};
12972
}]);

0 commit comments

Comments
 (0)