Skip to content

Commit 9842c8f

Browse files
authored
Merge pull request #613 from topcoder-platform/fix/schema
fix: handle older data types
2 parents fbdb428 + 38bbb15 commit 9842c8f

17 files changed

+137
-861
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ workflows:
8383
branches:
8484
only:
8585
- dev
86-
- fix/template
86+
- fix/schema
8787

8888
- "build-qa":
8989
context: org-global

README.md

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
# Topcoder Challenge API
22

33
This microservice provides access and interaction with all sorts of Challenge data.
4+
45
## Devlopment status
6+
57
[![Total alerts](https://img.shields.io/lgtm/alerts/g/topcoder-platform/challenge-api.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/topcoder-platform/challenge-api/alerts/)[![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/topcoder-platform/challenge-api.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/topcoder-platform/challenge-api/context:javascript)
68

79
### Deployment status
10+
811
Dev: [![CircleCI](https://circleci.com/gh/topcoder-platform/challenge-api/tree/develop.svg?style=svg)](https://circleci.com/gh/topcoder-platform/challenge-api/tree/develop) Prod: [![CircleCI](https://circleci.com/gh/topcoder-platform/challenge-api/tree/master.svg?style=svg)](https://circleci.com/gh/topcoder-platform/challenge-api/tree/master)
912

1013
## Swagger definition
1114

1215
- [Swagger](https://api.topcoder.com/v5/challenges/docs/)
1316

1417
## Intended use
18+
1519
- Production API
1620

1721
## Related repos
@@ -23,8 +27,8 @@ Dev: [![CircleCI](https://circleci.com/gh/topcoder-platform/challenge-api/tree/d
2327
- [Frontend App](https://github.com/topcoder-platform/challenge-engine-ui)
2428

2529
## Prerequisites
30+
2631
- [NodeJS](https://nodejs.org/en/) (v10)
27-
- [DynamoDB](https://aws.amazon.com/dynamodb/)
2832
- [AWS S3](https://aws.amazon.com/s3/)
2933
- [Elasticsearch v6](https://www.elastic.co/)
3034
- [Docker](https://www.docker.com/)
@@ -74,6 +78,7 @@ The following parameters can be set in config files or in env variables:
7478
You can find sample `.env` files inside the `/docs` directory.
7579

7680
## Available commands
81+
7782
1. Drop/delete tables: `npm run drop-tables`
7883
2. Creating tables: `npm run create-tables`
7984
3. Seed/Insert data to tables: `npm run seed-tables`
@@ -87,11 +92,12 @@ You can find sample `.env` files inside the `/docs` directory.
8792
11. Initialize the local environments: `npm run local:init`
8893
12. Reset the local environments: `npm run local:reset`
8994

90-
9195
### Notes
96+
9297
- The seed data are located in `src/scripts/seed`
9398

9499
## Local Deployment
100+
95101
0. Make sure to use Node v10+ by command `node -v`. We recommend using [NVM](https://github.com/nvm-sh/nvm) to quickly switch to the right version:
96102

97103
```bash
@@ -104,31 +110,33 @@ You can find sample `.env` files inside the `/docs` directory.
104110
yarn install
105111
```
106112

107-
2. ⚙ Local config
108-
In the `challenge-api` root directory create `.env` file with the next environment variables. Values for **Auth0 config** should be shared with you on the forum.<br>
109-
```bash
110-
# Auth0 config
111-
AUTH0_URL=
112-
AUTH0_PROXY_SERVER_URL=
113-
AUTH0_AUDIENCE=
114-
AUTH0_CLIENT_ID=
115-
AUTH0_CLIENT_SECRET=
113+
2. ⚙ Local config
114+
In the `challenge-api` root directory create `.env` file with the next environment variables. Values for **Auth0 config** should be shared with you on the forum.<br>
116115

117-
# Locally deployed services (via docker-compose)
118-
IS_LOCAL_DB=true
119-
DYNAMODB_URL=http://localhost:8000
120-
```
116+
```bash
117+
# Auth0 config
118+
AUTH0_URL=
119+
AUTH0_PROXY_SERVER_URL=
120+
AUTH0_AUDIENCE=
121+
AUTH0_CLIENT_ID=
122+
AUTH0_CLIENT_SECRET=
123+
124+
# Locally deployed services (via docker-compose)
125+
IS_LOCAL_DB=true
126+
DYNAMODB_URL=http://localhost:8000
127+
```
121128

122-
- Values from this file would be automatically used by many `npm` commands.
123-
- ⚠️ Never commit this file or its copy to the repository!
129+
- Values from this file would be automatically used by many `npm` commands.
130+
- ⚠️ Never commit this file or its copy to the repository!
124131

125132
3. 🚢 Start docker-compose with services which are required to start Topcoder Challenges API locally
126133

127134
```bash
128135
npm run services:up
129136
```
130-
137+
131138
4. ♻ Update following two parts:
139+
132140
- https://github.com/topcoder-platform/challenge-api/blob/develop/src/models/Challenge.js#L116
133141
`throughput: 'ON_DEMAND',` should be updated to `throughput:{ read: 4, write: 2 },`
134142
- https://github.com/topcoder-platform/challenge-api/blob/develop/config/default.js#L27-L28
@@ -147,15 +155,17 @@ You can find sample `.env` files inside the `/docs` directory.
147155
```
148156

149157
This command will do 3 things:
150-
- create Elasticsearch indexes (drop if exists)
151-
- Initialize the database by cleaning all the records.
152-
- Import the data to the local database and index it to ElasticSearch
158+
159+
- create Elasticsearch indexes (drop if exists)
160+
- Initialize the database by cleaning all the records.
161+
- Import the data to the local database and index it to ElasticSearch
153162

154163
7. 🚀 Start Topcoder Challenge API
155164

156165
```bash
157166
npm start
158167
```
168+
159169
The Topcoder Challenge API will be served on `http://localhost:3000`
160170

161171
## Production deployment
@@ -180,6 +190,7 @@ The following test parameters can be set in config file or in env variables:
180190
- S3_ENDPOINT: endpoint of AWS S3 API, for unit and e2e test only; default to `localhost:9000`
181191

182192
### Prepare
193+
183194
- Start Local services in docker.
184195
- Create DynamoDB tables.
185196
- Initialize ES index.
@@ -188,6 +199,7 @@ The following test parameters can be set in config file or in env variables:
188199
Seeding db data is not needed.
189200

190201
### Running unit tests
202+
191203
To run unit tests alone
192204

193205
```bash
@@ -201,6 +213,7 @@ npm run test:cov
201213
```
202214

203215
### Running integration tests
216+
204217
To run integration tests alone
205218

206219
```bash
@@ -214,6 +227,7 @@ npm run e2e:cov
214227
```
215228

216229
## Verification
230+
217231
Refer to the verification document `Verification.md`
218232

219233
## Notes

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
"dependencies": {
4343
"@grpc/grpc-js": "^1.8.12",
4444
"@opensearch-project/opensearch": "^2.2.0",
45-
"@topcoder-framework/domain-challenge": "^0.10.13",
46-
"@topcoder-framework/lib-common": "^0.10.13",
45+
"@topcoder-framework/domain-challenge": "^0.10.14",
46+
"@topcoder-framework/lib-common": "^0.10.14",
4747
"aws-sdk": "^2.1145.0",
4848
"axios": "^0.19.0",
4949
"axios-retry": "^3.4.0",
@@ -53,7 +53,6 @@
5353
"cors": "^2.7.1",
5454
"deep-equal": "^2.2.0",
5555
"dotenv": "^8.2.0",
56-
"dynamoose": "^1.11.1",
5756
"elasticsearch": "^16.7.3",
5857
"express": "^4.15.4",
5958
"express-fileupload": "^1.1.6",

src/common/challenge-helper.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ class ChallengeHelper {
365365
}
366366
});
367367
});
368-
if (overview && overview.totalPrizesInCents) {
368+
if (overview && !_.isUndefined(overview.totalPrizesInCents)) {
369369
overview.totalPrizes = overview.totalPrizesInCents / 100;
370370
delete overview.totalPrizesInCents;
371371
}

src/common/helper.js

Lines changed: 0 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ const Joi = require("joi");
55
const _ = require("lodash");
66
const querystring = require("querystring");
77
const constants = require("../../app-constants");
8-
const models = require("../models");
98
const errors = require("./errors");
109
const util = require("util");
1110
const AWS = require("aws-sdk");
@@ -184,155 +183,6 @@ function checkIfExists(source, term) {
184183
return false;
185184
}
186185

187-
/**
188-
* Get Data by model id
189-
* @param {String} modelName The dynamoose model name
190-
* @param {String} id The id value
191-
* @returns {Promise<void>}
192-
*/
193-
async function getById(modelName, id) {
194-
return new Promise((resolve, reject) => {
195-
models[modelName]
196-
.query("id")
197-
.eq(id)
198-
.exec((err, result) => {
199-
if (err) {
200-
return reject(err);
201-
}
202-
if (result.length > 0) {
203-
return resolve(result[0]);
204-
} else {
205-
return reject(new errors.NotFoundError(`${modelName} with id: ${id} doesn't exist`));
206-
}
207-
});
208-
});
209-
}
210-
211-
/**
212-
* Get Data by model ids
213-
* @param {String} modelName The dynamoose model name
214-
* @param {Array} ids The ids
215-
* @returns {Promise<Array>} the found entities
216-
*/
217-
async function getByIds(modelName, ids) {
218-
const entities = [];
219-
const theIds = ids || [];
220-
for (const id of theIds) {
221-
entities.push(await getById(modelName, id));
222-
}
223-
return entities;
224-
}
225-
226-
/**
227-
* Validate the data to ensure no duplication
228-
* @param {Object} modelName The dynamoose model name
229-
* @param {String} name The attribute name of dynamoose model
230-
* @param {String} value The attribute value to be validated
231-
* @returns {Promise<void>}
232-
*/
233-
async function validateDuplicate(modelName, name, value) {
234-
const list = await scan(modelName);
235-
for (let i = 0; i < list.length; i++) {
236-
if (list[i][name] && String(list[i][name]).toLowerCase() === String(value).toLowerCase()) {
237-
throw new errors.ConflictError(`${modelName} with ${name}: ${value} already exist`);
238-
}
239-
}
240-
}
241-
242-
/**
243-
* Create item in database
244-
* @param {Object} modelName The dynamoose model name
245-
* @param {Object} data The create data object
246-
* @returns {Promise<void>}
247-
*/
248-
async function create(modelName, data) {
249-
return new Promise((resolve, reject) => {
250-
const dbItem = new models[modelName](data);
251-
dbItem.save((err) => {
252-
if (err) {
253-
return reject(err);
254-
} else {
255-
return resolve(dbItem);
256-
}
257-
});
258-
});
259-
}
260-
261-
/**
262-
* Update item in database
263-
* @param {Object} dbItem The Dynamo database item
264-
* @param {Object} data The updated data object
265-
* @returns {Promise<void>}
266-
*/
267-
async function update(dbItem, data) {
268-
Object.keys(data).forEach((key) => {
269-
dbItem[key] = data[key];
270-
});
271-
return new Promise((resolve, reject) => {
272-
dbItem.save((err) => {
273-
if (err) {
274-
return reject(err);
275-
} else {
276-
return resolve(dbItem);
277-
}
278-
});
279-
});
280-
}
281-
282-
/**
283-
* Get data collection by scan parameters
284-
* @param {Object} modelName The dynamoose model name
285-
* @param {Object} scanParams The scan parameters object
286-
* @returns {Promise<void>}
287-
*/
288-
async function scan(modelName, scanParams) {
289-
return new Promise((resolve, reject) => {
290-
models[modelName].scan(scanParams).exec((err, result) => {
291-
if (err) {
292-
return reject(err);
293-
} else {
294-
return resolve(result.count === 0 ? [] : result);
295-
}
296-
});
297-
});
298-
}
299-
300-
/**
301-
* Get all data collection (avoid default page limit of DynamoDB) by scan parameters
302-
* @param {Object} modelName The dynamoose model name
303-
* @param {Object} scanParams The scan parameters object
304-
* @returns {Array}
305-
*/
306-
async function scanAll(modelName, scanParams) {
307-
let results = await models[modelName].scan(scanParams).exec();
308-
let lastKey = results.lastKey;
309-
while (!_.isUndefined(results.lastKey)) {
310-
const newResult = await models[modelName].scan(scanParams).startAt(lastKey).exec();
311-
results = [...results, ...newResult];
312-
lastKey = newResult.lastKey;
313-
}
314-
return results;
315-
}
316-
317-
/**
318-
* Test whether the given value is partially match the filter.
319-
* @param {String} filter the filter
320-
* @param {String} value the value to test
321-
* @returns {Boolean} the match result
322-
*/
323-
function partialMatch(filter, value) {
324-
if (filter) {
325-
if (value) {
326-
const filtered = xss(filter);
327-
return _.toLower(value).includes(_.toLower(filtered));
328-
} else {
329-
return false;
330-
}
331-
} else {
332-
return true;
333-
}
334-
}
335-
336186
/**
337187
* Download file from S3
338188
* @param {String} bucket the bucket name
@@ -1322,14 +1172,6 @@ module.exports = {
13221172
setResHeaders,
13231173
checkIfExists,
13241174
toString,
1325-
getById,
1326-
getByIds,
1327-
create,
1328-
update,
1329-
scan,
1330-
scanAll,
1331-
validateDuplicate,
1332-
partialMatch,
13331175
downloadFromFileStack,
13341176
downloadFromS3,
13351177
deleteFromS3,

0 commit comments

Comments
 (0)