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

Commit 51e5cfb

Browse files
authored
Merge pull request #118 from topcoder-platform/develop
PROD - Standardized skills support and preliminary private fork implementation
2 parents 5e902db + 13e2911 commit 51e5cfb

34 files changed

+7149
-3203
lines changed

.circleci/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ install_dependency: &install_dependency
99
sudo apt install jq
1010
sudo apt install python3-pip
1111
sudo pip3 install awscli --upgrade
12+
sudo pip3 install docker==6.1.3
1213
sudo pip3 install docker-compose
1314
install_deploysuite: &install_deploysuite
1415
name: Installation of install_deploysuite.

.eslintrc

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
"node": true,
44
"mocha": true
55
},
6+
"plugins": [
7+
"jsdoc"
8+
],
69
"parserOptions": {
7-
"ecmaVersion": 8,
10+
"ecmaVersion": 2023,
811
"ecmaFeatures": {
912
"experimentalObjectRestSpread": true
1013
}
@@ -42,7 +45,10 @@
4245
"functions": "ignore"
4346
}
4447
],
48+
"import/no-unresolved": 0,
49+
"max-params": 0,
4550
"max-lines": 0,
46-
"max-statements": 0
51+
"max-statements": 0,
52+
"valid-jsdoc": 0
4753
}
48-
}
54+
}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@
66
*.cer
77
*.key
88
.idea
9+
10+
.env
11+
.envrc

config/default.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ module.exports = {
1616
LOG_LEVEL: process.env.LOG_LEVEL || 'debug',
1717
PARTITION: process.env.PARTITION || 0,
1818
TOPIC: process.env.TOPIC || 'tc-x-events',
19+
TOPIC_CHALLENGE_ACTION_RESOURCE_CREATE: process.env.TOPIC_CHALLENGE_ACTION_RESOURCE_CREATE || 'challenge.action.resource.create',
1920
TOPIC_NOTIFICATION: process.env.TOPIC_NOTIFICATION || 'notifications.action.create',
2021
KAFKA_OPTIONS: {
2122
connectionString: process.env.KAFKA_URL || 'localhost:9092',
2223
groupId: process.env.KAFKA_GROUP_ID || 'topcoder-x-processor',
23-
ssl: {
24+
ssl: process.env.KAFKA_DISABLE_SSL ? false : {
2425
cert: process.env.KAFKA_CLIENT_CERT || fs.readFileSync('./kafka_client.cer'), // eslint-disable-line no-sync
2526
key: process.env.KAFKA_CLIENT_CERT_KEY || fs.readFileSync('./kafka_client.key'), // eslint-disable-line no-sync
2627
passphrase: 'secret', // NOTE:* This configuration specifies the private key passphrase used while creating it.
@@ -67,17 +68,19 @@ module.exports = {
6768
GRANT_TYPE: 'client_credentials',
6869

6970
// used as base to construct various URLs
70-
WEBSITE_SECURE: process.env.WEBSITE_SECURE || 'https://topcoderx.topcoder-dev.com',
71+
WEBSITE_SECURE: process.env.WEBSITE_SECURE || 'http://topcoderx.topcoder-dev.com',
7172

7273
ROLE_ID_COPILOT: process.env.ROLE_ID_COPILOT || 'cfe12b3f-2a24-4639-9d8b-ec86726f76bd',
7374
ROLE_ID_ITERATIVE_REVIEWER: process.env.ROLE_ID_ITERATIVE_REVIEWER || 'f6df7212-b9d6-4193-bfb1-b383586fce63',
7475
ROLE_ID_SUBMITTER: process.env.ROLE_ID_SUBMITTER || '732339e7-8e30-49d7-9198-cccf9451e221',
7576
TYPE_ID_TASK: process.env.TYPE_ID_TASK || 'ecd58c69-238f-43a4-a4bb-d172719b9f31',
7677
DEFAULT_TIMELINE_TEMPLATE_ID: process.env.DEFAULT_TIMELINE_TEMPLATE_ID || '53a307ce-b4b3-4d6f-b9a1-3741a58f77e6',
7778
DEFAULT_TRACK_ID: process.env.DEFAULT_TRACK_ID || '9b6fc876-f4d9-4ccb-9dfd-419247628825',
79+
WORK_TYPE_ID: process.env.WORK_TYPE_ID || 'b658b280-6c4d-11e5-9d70-22000b2c9aef',
7880
GITLAB_ACCESS_TOKEN_DEFAULT_EXPIRATION: 3600 * 2,
7981
GITLAB_REFRESH_TOKEN_BEFORE_EXPIRATION: 300,
8082
GITLAB_CLIENT_ID: process.env.GITLAB_CLIENT_ID,
8183
GITLAB_CLIENT_SECRET: process.env.GITLAB_CLIENT_SECRET,
82-
GITLAB_OWNER_USER_CALLBACK_URL: process.env.GITLAB_OWNER_USER_CALLBACK_URL
84+
GITLAB_OWNER_USER_CALLBACK_URL: process.env.GITLAB_OWNER_USER_CALLBACK_URL,
85+
GITLAB_GUEST_USER_CALLBACK_URL: process.env.GITLAB_GUEST_USER_CALLBACK_URL
8386
};

constants.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ const USER_TYPES = {
1919

2020
// The user roles
2121
const USER_ROLES = {
22-
OWNER: 'owner'
22+
OWNER: 'owner',
23+
GUEST: 'guest'
2324
};
2425

2526
// The challenge status
@@ -43,10 +44,20 @@ const ISSUE_STATUS = {
4344
CHALLENGE_PAYMENT_FAILED: 'challenge_payment_failed'
4445
};
4546

47+
const GITLAB_ACCESS_LEVELS = {
48+
NO_ACCESS: 0,
49+
GUEST: 10,
50+
REPORTER: 20,
51+
DEVELOPER: 30,
52+
MAINTAINER: 40,
53+
OWNER: 50
54+
};
55+
4656
module.exports = {
4757
USER_ROLES,
4858
USER_TYPES,
4959
SERVICE_ERROR_STATUS,
5060
CHALLENGE_STATUS,
51-
ISSUE_STATUS
61+
ISSUE_STATUS,
62+
GITLAB_ACCESS_LEVELS
5263
};

docker/Dockerfile

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
11
# Use the base image with Node.js
2-
FROM node:8.12
2+
FROM node:20
33

4-
# Copy the current directory into the Docker image
5-
COPY . /topcoder-x-processor
6-
7-
# Set working directory for future use
84
WORKDIR /topcoder-x-processor
5+
COPY package.json package-lock.json ./
6+
RUN npm ci --silent --legacy-peer-deps
7+
COPY . .
98

10-
# Install the dependencies from package.json
11-
RUN npm install
12-
#RUN npm run build
13-
#RUN npm run test
14-
15-
CMD npm start
9+
CMD node ./index.js

models/CopilotPayment.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@ const dynamoose = require('dynamoose');
1414

1515
const Schema = dynamoose.Schema;
1616

17+
/**
18+
* @typedef {Object} CopilotPayment
19+
* @property {String} id The unique identifier for the CopilotPayment entity.
20+
* @property {String} project The project associated with the payment.
21+
* @property {Number} amount The payment amount.
22+
* @property {String} description The description of the payment.
23+
* @property {Number} challengeId The ID of the associated challenge (if applicable).
24+
* @property {String} challengeUUID The UUID of the associated challenge (if applicable).
25+
* @property {String} closed Indicates whether the payment is closed or not (default is 'false').
26+
* @property {String} username The username of the Copilot receiving the payment.
27+
* @property {String} status The status of the payment.
28+
*/
29+
1730
const schema = new Schema({
1831
id: {
1932
type: String,

models/GithubUserMapping.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ const dynamoose = require('dynamoose');
77

88
const Schema = dynamoose.Schema;
99

10+
/**
11+
* @typedef {Object} GithubUserMapping
12+
* @property {String} id The unique identifier for the GithubUserMapping entity.
13+
* @property {String} topcoderUsername The Topcoder username associated with the GitHub user.
14+
* @property {String} githubUsername The GitHub username.
15+
* @property {Number} githubUserId The GitHub user's numeric identifier.
16+
*/
17+
1018
const schema = new Schema({
1119
id: {
1220
type: String,

models/GitlabUserMapping.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ const dynamoose = require('dynamoose');
77

88
const Schema = dynamoose.Schema;
99

10+
/**
11+
* @typedef {Object} GitlabUserMapping
12+
* @property {String} id The unique identifier for the GitlabUserMapping entity.
13+
* @property {String} topcoderUsername The Topcoder username associated with the GitLab user.
14+
* @property {String} gitlabUsername The GitLab username.
15+
* @property {Number} gitlabUserId The GitLab user's numeric identifier.
16+
*/
17+
1018
const schema = new Schema({
1119
id: {
1220
type: String,

models/Issue.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,27 @@ const dynamoose = require('dynamoose');
1212

1313
const Schema = dynamoose.Schema;
1414

15+
/**
16+
* @typedef {Object} Issue
17+
* @property {String} id The id.
18+
* @property {Number} number From the receiver service.
19+
* @property {String} title The title.
20+
* @property {String} body The body.
21+
* @property {Number[]} prizes Prizes extracted from title.
22+
* @property {String} provider Provider (github or gitlab).
23+
* @property {Number} repositoryId Repository ID.
24+
* @property {String} repoUrl Repository URL.
25+
* @property {String} repositoryIdStr Repository ID as a String.
26+
* @property {Array} labels Labels associated with the issue.
27+
* @property {String} assignee Assignee for the issue.
28+
* @property {Date} updatedAt Date when the issue was last updated.
29+
* @property {Number} challengeId Challenge ID from topcoder API.
30+
* @property {String} challengeUUID Challenge UUID.
31+
* @property {String} projectId Project ID.
32+
* @property {String} status Status of the issue.
33+
* @property {Date} assignedAt Date when the issue was assigned (if applicable).
34+
*/
35+
1536
const schema = new Schema({
1637
id: {type: String, hashKey: true, required: true},
1738
// From the receiver service

models/Project.js

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,23 @@ const dynamoose = require('dynamoose');
1212

1313
const Schema = dynamoose.Schema;
1414

15+
/**
16+
* @typedef {Object} ProjectChallengeMapping
17+
* @property {String} id The id.
18+
* @property {String} title The title.
19+
* @property {Number} tcDirectId The tc direct id.
20+
* @property {Array<{id: string, name: string}>} tags The tags.
21+
* @property {String} rocketChatWebhook The rocket chat webhook.
22+
* @property {String} rocketChatChannelName The rocket chat channel name.
23+
* @property {String} archived The archived.
24+
* @property {String} owner The owner.
25+
* @property {String} secretWebhookKey The secret webhook key.
26+
* @property {String} copilot The copilot.
27+
* @property {Date} updatedAt The updated at.
28+
* @property {String} createCopilotPayments The create copilot payments.
29+
* @property {Boolean} isConnect Is Topcoder connect.
30+
*/
31+
1532
const schema = new Schema({
1633
id: {
1734
type: String,
@@ -24,9 +41,33 @@ const schema = new Schema({
2441
required: true
2542
},
2643
tags: {
27-
type: String,
44+
type: 'list',
45+
list: [{
46+
type: 'map',
47+
map: {
48+
id: {type: String, required: true},
49+
name: {type: String, required: true}
50+
}
51+
}],
2852
required: true,
29-
default: ''
53+
default: [],
54+
fromDynamo(value) {
55+
if (value.S) {
56+
return value.S;
57+
}
58+
if (value.L) {
59+
return value.L.map((item) => {
60+
if (item.M && item.M.name && item.M.id) {
61+
return {
62+
id: item.M.id.S,
63+
name: item.M.name.S
64+
};
65+
}
66+
return null;
67+
});
68+
}
69+
return [];
70+
}
3071
},
3172
rocketChatWebhook: {type: String, required: false},
3273
rocketChatChannelName: {type: String, required: false},

models/ProjectChallengeMapping.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) 2017 TopCoder, Inc. All rights reserved.
3+
*/
4+
'use strict';
5+
6+
/**
7+
* This defines TCX project to TC challenge mapping model.
8+
*/
9+
const dynamoose = require('dynamoose');
10+
11+
const Schema = dynamoose.Schema;
12+
13+
/**
14+
* @typedef {Object} ProjectChallengeMapping
15+
* @property {String} id the id
16+
* @property {String} projectId the project id
17+
* @property {String} challengeId the challenge id
18+
*/
19+
20+
const schema = new Schema({
21+
id: {
22+
type: String,
23+
required: true,
24+
hashKey: true
25+
},
26+
projectId: {
27+
type: String,
28+
required: true,
29+
index: {
30+
global: true,
31+
project: true,
32+
name: 'ProjectIdIndex'
33+
}
34+
},
35+
challengeId: {
36+
type: String,
37+
required: true
38+
}
39+
});
40+
41+
module.exports = schema;

models/Repository.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@ const dynamoose = require('dynamoose');
1212

1313
const Schema = dynamoose.Schema;
1414

15+
/**
16+
* @typedef {Object} Repository
17+
* @property {String} id The unique identifier for the Repository entity.
18+
* @property {String} projectId The project ID associated with the repository.
19+
* @property {String} url The URL of the repository.
20+
* @property {String} archived Indicates whether the repository is archived or not.
21+
* @property {String} repoId The repository ID (if applicable).
22+
* @property {String} registeredWebhookId The ID of the registered webhook (if applicable).
23+
*/
24+
1525
const schema = new Schema({
1626
id: {
1727
type: String,

models/User.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,21 @@ const constants = require('../constants');
1212

1313
const Schema = dynamoose.Schema;
1414

15+
/**
16+
* @typedef {Object} User
17+
* @property {String} id The user's unique identifier.
18+
* @property {Number} userProviderId The user provider's numeric identifier.
19+
* @property {String} userProviderIdStr The user provider's identifier as a string.
20+
* @property {String} username The user's username.
21+
* @property {String} role The user's role, one of the allowed constants.USER_ROLES.
22+
* @property {String} type The user's type, one of the allowed constants.USER_TYPES.
23+
* @property {String} accessToken GitLab token data (if applicable).
24+
* @property {Date} accessTokenExpiration Expiration date of the access token (if applicable).
25+
* @property {String} refreshToken GitLab token refresh token (if applicable).
26+
* @property {String} lockId Lock identifier (if applicable).
27+
* @property {Date} lockExpiration Expiration date of the lock (if applicable).
28+
*/
29+
1530
const schema = new Schema({
1631
id: {
1732
type: String,
@@ -49,7 +64,9 @@ const schema = new Schema({
4964
// gitlab token data
5065
accessToken: {type: String, required: false},
5166
accessTokenExpiration: {type: Date, required: false},
52-
refreshToken: {type: String, required: false}
67+
refreshToken: {type: String, required: false},
68+
lockId: {type: String, required: false},
69+
lockExpiration: {type: Date, required: false}
5370
});
5471

5572
module.exports = schema;

models/index.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,23 @@ if (process.env.CREATE_DB) {
3535

3636
/* eslint-disable global-require */
3737
const models = {
38+
/** @type {import('dynamoose').ModelConstructor<import('./Issue').Issue>} */
3839
Issue: dynamoose.model('Topcoder_X.Issue', require('./Issue')),
40+
/** @type {import('dynamoose').ModelConstructor<import('./Project').Project>} */
3941
Project: dynamoose.model('Topcoder_X.Project', require('./Project')),
42+
/** @type {import('dynamoose').ModelConstructor<import('./ProjectChallengeMapping').ProjectChallengeMapping>} */
43+
ProjectChallengeMapping: dynamoose.model('Topcoder_X.ProjectChallengeMapping', require('./ProjectChallengeMapping')),
44+
/** @type {import('dynamoose').ModelConstructor<import('./User').User>} */
4045
User: dynamoose.model('Topcoder_X.User', require('./User')),
46+
/** @type {import('dynamoose').ModelConstructor<import('./CopilotPayment').CopilotPayment>} */
4147
CopilotPayment: dynamoose.model('Topcoder_X.CopilotPayment', require('./CopilotPayment')),
48+
/** @type {import('dynamoose').ModelConstructor<import('./GithubUserMapping').GithubUserMapping>} */
4249
GithubUserMapping: dynamoose.model('Topcoder_X.GithubUserMapping', require('./GithubUserMapping')),
50+
/** @type {import('dynamoose').ModelConstructor<import('./GitlabUserMapping').GitlabUserMapping>} */
4351
GitlabUserMapping: dynamoose.model('Topcoder_X.GitlabUserMapping', require('./GitlabUserMapping')),
52+
/** @type {import('dynamoose').ModelConstructor<import('./Repository').Repository>} */
4453
Repository: dynamoose.model('Topcoder_X.Repository', require('./Repository'))
4554
};
4655
/* eslint-enable global-require */
4756

48-
4957
module.exports = models;

0 commit comments

Comments
 (0)