diff --git a/.circleci/config.yml b/.circleci/config.yml
index b813779aa7..621db64129 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -33,10 +33,10 @@ install_deploysuite: &install_deploysuite
cp ./../buildscript/buildenv.sh .
cp ./../buildscript/awsconfiguration.sh .
restore_cache_settings_for_build: &restore_cache_settings_for_build
- key: docker-node-modules-v4-{{ checksum "package-lock.json" }}
+ key: docker-node-modules-v3-{{ checksum "package-lock.json" }}
save_cache_settings: &save_cache_settings
- key: docker-node-modules-v4-{{ checksum "package-lock.json" }}
+ key: docker-node-modules-v3-{{ checksum "package-lock.json" }}
paths:
- node_modules
@@ -73,7 +73,7 @@ jobs:
command: |
source awsenvconf
source buildenvvar
- ./master_deploy.sh -d ECS -e DEV -t latest -s dev_communityapp_taskvar -i communityapp -p FARGATE
+ ./master_deploy.sh -d ECS -e DEV -t latest -s dev_communityapp_taskvar -i communityapp
# Build & Deploy against testing backend
# "build-test":
@@ -224,7 +224,7 @@ jobs:
command: |
source awsenvconf
source buildenvvar
- ./master_deploy.sh -d ECS -e PROD -t latest -s prod_communityapp_taskvar -i communityapp -p FARGATE
+ ./master_deploy.sh -d ECS -e PROD -t latest -s prod_communityapp_taskvar -i communityapp
curl --request POST \
--url https://circleci.com/api/v2/project/github/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/pipeline \
--header "Circle-Token: ${CIRCLE_TOKEN}" \
@@ -260,37 +260,37 @@ jobs:
# path: ./automated-smoke-test/test-results
# Automated Smoke Testing against Production
- # Smoke-Testing-On-Production:
- # <<: *defaults
- # steps:
- # # Initialization.
- # - checkout
- # - setup_remote_docker
- # - run: *install_dependency
- # - run: *install_deploysuite
- # # Restoration of node_modules from cache.
- # - restore_cache: *restore_cache_settings_for_build
- # - run:
- # name: "configuring environment"
- # command: |
- # ./awsconfiguration.sh PROD
- # ./buildenv.sh -e PROD -b prod_communityapp_buildvar,prod_communityapp_deployvar
- # - run:
- # name: "Run automation"
- # no_output_timeout: 20m
- # command: |
- # source awsenvconf
- # source buildenvvar
- # ./automated-smoke-test/smoketest.sh automation-config-prod.json prod
- # - store_artifacts:
- # path: ./automated-smoke-test/test-results
+ Smoke-Testing-On-Production:
+ <<: *defaults
+ steps:
+ # Initialization.
+ - checkout
+ - setup_remote_docker
+ - run: *install_dependency
+ - run: *install_deploysuite
+ # Restoration of node_modules from cache.
+ - restore_cache: *restore_cache_settings_for_build
+ - run:
+ name: "configuring environment"
+ command: |
+ ./awsconfiguration.sh PROD
+ ./buildenv.sh -e PROD -b prod_communityapp_buildvar,prod_communityapp_deployvar
+ - run:
+ name: "Run automation"
+ no_output_timeout: 20m
+ command: |
+ source awsenvconf
+ source buildenvvar
+ ./automated-smoke-test/smoketest.sh automation-config-prod.json prod
+ - store_artifacts:
+ path: ./automated-smoke-test/test-results
# Test job for the cases when we do not need deployment. It just rapidly
# installs (updates) app dependencies, and runs tests (ESLint, Stylelint,
# Jest unit-tests).
test:
docker:
- - image: circleci/node:10.24.1
+ - image: circleci/node:8.11.1
steps:
- checkout
- restore_cache:
@@ -360,7 +360,6 @@ workflows:
- develop
- TOP-1390
- PM-191-2
- - pm-199
# This is alternate dev env for parallel testing
# Deprecate this workflow due to beta env shutdown
# https://topcoder.atlassian.net/browse/CORE-251
diff --git a/Dockerfile b/Dockerfile
index 0e7f8c6e2c..7691feebdc 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,16 +2,12 @@
# and runs it against the specified Topcoder backend (development or
# production) when container is executed.
-FROM node:10.24.1
+FROM node:8.11.2
LABEL app="Community App" version="1.0"
-RUN useradd -m -s /bin/bash appuser
WORKDIR /opt/app
COPY . .
-RUN chown -R appuser:appuser /opt/app
-USER appuser
-
################################################################################
# Receiving of build arguments.
diff --git a/__tests__/shared/components/Settings/Account/__snapshots__/index.jsx.snap b/__tests__/shared/components/Settings/Account/__snapshots__/index.jsx.snap
new file mode 100644
index 0000000000..207666379e
--- /dev/null
+++ b/__tests__/shared/components/Settings/Account/__snapshots__/index.jsx.snap
@@ -0,0 +1,2132 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders account setting page correctly 1`] = `
+
+ Account information & Security
+
+
- <code>
+ <code goes here>
@@ -1294,7 +1294,7 @@ end tell
ampersands and angle brackets. For example, this:
,
- <div>
+ <div class="footer">
© 2004 Foo Corporation
</div>
diff --git a/automated-smoke-test/Dockerfile b/automated-smoke-test/Dockerfile
new file mode 100644
index 0000000000..b228769e64
--- /dev/null
+++ b/automated-smoke-test/Dockerfile
@@ -0,0 +1,32 @@
+FROM node:10.17.0-stretch
+RUN apt update
+RUN apt install sudo
+RUN sudo apt-get update; sudo apt-get install -y openjdk-8-jre openjdk-8-jre-headless openjdk-8-jdk openjdk-8-jdk-headless;
+RUN curl --silent --show-error --location --fail --retry 3 --output /tmp/google-chrome-stable_current_amd64.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb \
+ && (sudo dpkg -i /tmp/google-chrome-stable_current_amd64.deb || sudo apt-get -fy install) \
+ && rm -rf /tmp/google-chrome-stable_current_amd64.deb \
+ && sudo sed -i 's|HERE/chrome"|HERE/chrome" --disable-setuid-sandbox --no-sandbox|g' \
+ "/opt/google/chrome/google-chrome" \
+ && google-chrome --version
+RUN export CHROMEDRIVER_RELEASE=$(curl --location --fail --retry 3 http://chromedriver.storage.googleapis.com/LATEST_RELEASE) \
+ && curl --silent --show-error --location --fail --retry 3 --output /tmp/chromedriver_linux64.zip "http://chromedriver.storage.googleapis.com/$CHROMEDRIVER_RELEASE/chromedriver_linux64.zip" \
+ && cd /tmp \
+ && unzip chromedriver_linux64.zip \
+ && rm -rf chromedriver_linux64.zip \
+ && sudo mv chromedriver /usr/local/bin/chromedriver \
+ && sudo chmod +x /usr/local/bin/chromedriver \
+ && chromedriver --version
+RUN sudo apt-get install -y libgconf-2-4
+RUN sudo apt-get install -y xvfb
+RUN sudo apt-get install -y jq
+ENV DISPLAY :99
+RUN printf '#!/bin/sh\nXvfb :99 -screen 0 1280x1024x24 &\nexec "$@"\n' > /tmp/entrypoint \
+ && chmod +x /tmp/entrypoint \
+ && sudo mv /tmp/entrypoint /docker-entrypoint.sh
+
+COPY . /automated-smoke-test
+WORKDIR /automated-smoke-test
+RUN npm install
+RUN ./node_modules/.bin/webdriver-manager update --versions.chrome=="$(google-chrome -version)"
+ENTRYPOINT ["/docker-entrypoint.sh"]
+CMD ["/bin/sh"]
\ No newline at end of file
diff --git a/automated-smoke-test/config/automation-config-dev.json b/automated-smoke-test/config/automation-config-dev.json
index 9ac9bf711d..4df4b85ad3 100644
--- a/automated-smoke-test/config/automation-config-dev.json
+++ b/automated-smoke-test/config/automation-config-dev.json
@@ -86,6 +86,7 @@
"allNotificationsUrl": "https://community-app.topcoder-dev.com/notifications",
"policiesUrl": "https://community-app.topcoder-dev.com/policy",
"username": "tester1234",
+ "password": "appirio123",
"email": "sathya.jayabal@gmail.com",
"challangesLinks": {
"rssFeedUrl": "http://feeds.topcoder-dev.com/challenges/feed",
diff --git a/automated-smoke-test/config/automation-config-local.json b/automated-smoke-test/config/automation-config-local.json
index c2ca342f56..79f61ba285 100644
--- a/automated-smoke-test/config/automation-config-local.json
+++ b/automated-smoke-test/config/automation-config-local.json
@@ -81,6 +81,7 @@
"allNotificationsUrl": "http://localhost:3000/notifications",
"policiesUrl": "http://localhost:3000/policy",
"username": "Tonyj",
+ "password": "appirio123",
"email": "topcoderconnect@gmail.com",
"challangesLinks": {
"rssFeedUrl": "http://feeds.topcoder.com/challenges/feed",
diff --git a/automated-smoke-test/config/automation-config-prod.json b/automated-smoke-test/config/automation-config-prod.json
index d05c56008c..ed2fc420de 100644
--- a/automated-smoke-test/config/automation-config-prod.json
+++ b/automated-smoke-test/config/automation-config-prod.json
@@ -81,6 +81,7 @@
"allNotificationsUrl": "https://www.topcoder.com/notifications",
"policiesUrl": "https://www.topcoder.com/policy",
"username": "CustomerUser",
+ "password": "appirio123",
"email": "topcoderconnect@gmail.com",
"challangesLinks": {
"rssFeedUrl": "http://feeds.topcoder.com/challenges/feed",
diff --git a/automated-smoke-test/test-data/test-data.json b/automated-smoke-test/test-data/test-data.json
index 98fcf8a0bc..02aa602405 100644
--- a/automated-smoke-test/test-data/test-data.json
+++ b/automated-smoke-test/test-data/test-data.json
@@ -1,6 +1,7 @@
{
"login": {
- "invalidUsername": "gjhhvv"
+ "invalidUsername": "gjhhvv",
+ "invalidPassword": "invalidpassword"
},
"tools": {
"subscription": "Sample A",
diff --git a/config/default.js b/config/default.js
index f5424d3504..e30ec05227 100644
--- a/config/default.js
+++ b/config/default.js
@@ -132,8 +132,8 @@ module.exports = {
INFO: {
DESIGN_CHALLENGES: 'http://help.topcoder.com/hc/en-us/categories/202610437-DESIGN',
DESIGN_CHALLENGE_CHECKPOINTS: 'https://help.topcoder.com/hc/en-us/articles/219240807-Multi-Round-Checkpoint-Design-Challenges',
- DESIGN_CHALLENGE_SUBMISSION: 'https://www.topcoder.com/thrive/articles/Formatting%20Your%20Submission%20for%20Design%20Challenges',
- DESIGN_CHALLENGE_TYPES: 'https://www.topcoder.com/thrive/articles/How%20To%20Compete%20in%20Design',
+ DESIGN_CHALLENGE_SUBMISSION: 'http://help.topcoder.com/hc/en-us/articles/219122667-Formatting-Your-Submission-for-Design-Challenges',
+ DESIGN_CHALLENGE_TYPES: 'http://help.topcoder.com/hc/en-us/articles/217481388-Choosing-a-Design-Challenge',
RELIABILITY_RATINGS_AND_BONUSES: 'https://www.topcoder.com/thrive/articles/Development%20Reliability%20Ratings%20and%20Bonuses',
STOCK_ART_POLICY: 'http://help.topcoder.com/hc/en-us/articles/217481408-Policy-for-Stock-Artwork-in-Design-Submissions',
STUDIO_FONTS_POLICY:
diff --git a/docs/contentful/AppComponent.md b/docs/contentful/AppComponent.md
index a937f7b942..12c3980e17 100644
--- a/docs/contentful/AppComponent.md
+++ b/docs/contentful/AppComponent.md
@@ -46,6 +46,8 @@ Render top spots and list of competitors on specific TCO track.
A block that fetches and renders a job listing page driven by recruitCRM.
+### Type = `EmailSubscribeForm`
+
Generic subscribe for MailChimp tags component.
- **listId** | **String (Required).**
diff --git a/docs/contentful/custom-inline-components-in-markdown-fields.md b/docs/contentful/custom-inline-components-in-markdown-fields.md
index 4961ffe946..da252c165b 100644
--- a/docs/contentful/custom-inline-components-in-markdown-fields.md
+++ b/docs/contentful/custom-inline-components-in-markdown-fields.md
@@ -69,6 +69,22 @@ other types too.
| listId | | ID of MailChimp list to subscribe. |
| interests | empty string | Optional. commas separated string of group ids to which user should be subscribed |
+- #### NewsletterSignupForMembers
+ **Sample use:** ` `
+
+ Renders a newsletter signup button that takes user email from his profile
+ information. If the user is not-authenticated, it gets him to the login or
+ registration page, and subscribes him on return. Accepts the following props:
+
+ | Param | Default | Description |
+ | --- | --- | --- |
+ | label | Subscribe for Newsletter | Optional. Custom label to show on the button. |
+ | listId | | ID of MailChimp list to subscribe. |
+ | tags | | ID of MailChimp tags to subscribe. |
+ | buttonTheme | primary-green-md | Theme key(`tc-` is omitted) for the button. See https://community-app.topcoder.com/examples/contentful/contentblock/3k7k1JpnSvIRrJYWs4izYi |
+ | title | Sign up for the Topcoder Newsletter | Modal title |
+ | desc | Do you want to subscribe to this newsletter? | Modal description |
+
- #### VideoModalButton
*Example:* ` `
@@ -82,6 +98,14 @@ other types too.
component works only with YouTube videos, and the URL should be similar to
`https://www.youtube.com/embed/mD12LIqdxqk` ().
+- #### NewsletterArchive
+ *Example:* ` `
+
+ A list of archive links sorted by descending `sent_date` from a MailChimp's campaign folder. Sould be working under any MarkdownParser component.
+
+ The properties are:
+ - `name` - the unique name of the camplaing foler. It has to be only one name entity. If those duplicate first found will be picked up and rest ignored.
+
## Links
- #### Link
diff --git a/docs/pwa/nginx/server.key b/docs/pwa/nginx/server.key
new file mode 100644
index 0000000000..3e46bd6691
--- /dev/null
+++ b/docs/pwa/nginx/server.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDXKekFdnLsjrnq
+4RMF/V6ewrDRwzt9gVJXX8aEemq5wDjrnK1q2SJBrEMQw72T1oIt8TJs+d6HLc0K
+DX3MILdix/r/+ML5bVjTd6HdzqXnbsd9omvZ3a43QKLxGCvqwe0iN8C7106++nik
+3issH6qiQh5p5ERN8gApSyj0/PIu051YCNL8SpsqDiRHtWzZt07ncPFPueINXdRu
+AEb7pod7tIvBnI2kudJx4d2AX+lE7eOhsvCr0eHS3/V03BlprAt3qw7c2ZwLxTYZ
+D/l6NgCoy6AQfq9d7XikTVFx9ZKiuCPVS11PzI6G2pbx5Y6ewHdcfLnPVIDKPfMh
+L3SjmDTNAgMBAAECggEAOLf3kVUUHn/RSrViSmXsF3XDHsiUWhVJG3dH4YxTrfua
+BaIbpNrwSNecJkMzKlGVp365iDimDIRqVIgR7UmCjiuhYvC0lQPaMoSKyum6mjN9
+qwSx4ZCqaC5FxcBVc2EDnc2MpPew7m8gdnWKc+s1E+jSE5/00YdFu5zwgwRa4zSx
+TquwlMGd6AcE1J5YbxYGJRztAl2VKguBJFcSnnFef8xY18GoEO1lt43ef9ijsfL3
+mBccrlLWQmc1CxM8zZ83lD1yW41bcwMhx7XCgRZjhDtNmbyWWJOYoFwojtAxFqG4
+VHFKjY+kNgIWjKZim84GA3tUPS/L832GXYk6SyC6kQKBgQD/HsnCryGTaitjwn+5
+FbPWlBnnGn1hxE36g0u1B3A/mQ3Jut949Dsm9vEoS1gHOQBCc5cE3RXNZ6iZdSDc
+Lf9YzZnchIgjauU9bqkZVI2RSPnNOTjWjXhGtrZxrc4eckRWqbChmYX0qCxokwhb
+leIdmJy7Y0Q6ttVGAHySoC/h7wKBgQDX59mKR1Gm7rKcEqW2aWhz878Xft/OHchh
+THF9EUGHWXOYiKDAPxV6+xg2ZZaPUorMdp588iC3dd0YRn/KSkFlYWIgA8yYkjI7
+Al6pwGgOPw8k2/t1Rxfw2NUJr/19dAqMSyxDZ6W1OsGsdoAIgOMQxx12zENZpX6y
+xcewsWNhAwKBgQC33vbHa/WlC4YONmZbfTrKUp+AouTvC86v2OU9qgjKrYL0e80I
+ne3sHVqeEf915S08t5aGmNlX23f2ciamyjgZRsW324VLEYX7CsCxUvFdXt07fhxq
+9jdTr+g6cmv2IaEDXPXC4qVbOcIX9LC3YYVAk3eSzu6j6pY4B63A99bK3QKBgQDE
+d/mQiGe4BVxJA/sB7Bed9D9+7PhSAu4WBE79pVdBCFhVhHbrmjw8xgN5dKY2U8F0
+X7jHMDovWDTSY0zkUwABdkWppmtmpxrIcdacmDbYR+/K9dd0GDaj91ydTSXaJF94
+3Osxhz7WlNoqy0ak9kwqN1cLhMMA78VEfw/BLRqm6wKBgGUZNlOXQjcAcFjZ12Z4
+3X3tOWjwAPx2D5kT99Jh2BDgzjOci303MDnxI+mb6BQY32mz5+2OlD+bz2qYHVPp
+9+Ir9WNbIl+DCUadRcPuYPAwPSftBEKzH901BBXHnbSkLSWocvLqYxUBjJ64KTh0
+2OTOU4OPRrct2tauUUyPRiBX
+-----END PRIVATE KEY-----
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
new file mode 100644
index 0000000000..19cc61f8d6
--- /dev/null
+++ b/docs/swagger.yaml
@@ -0,0 +1,196 @@
+openapi: 3.0.0
+info:
+ title: Community APP
+ description: Community APP
+ version: 1.0.0
+servers:
+ - url: http://local.topcoder-dev.com:3000
+tags:
+ - name: Profile
+paths:
+ /api/recruit/profile:
+ get:
+ tags:
+ - Profile
+ description: |
+ Get Profile of current user
+
+ **Authorization** All topcoder members are allowed.
+ security:
+ - bearerAuth: []
+ responses:
+ "200":
+ description: OK
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: "#/components/schemas/Profile"
+ "401":
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/AuthError"
+ "403":
+ description: Forbidden
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/AuthError"
+ "404":
+ description: Not Found
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Profile"
+ "500":
+ description: Internal Server Error
+ content:
+ text/plain::
+ schema:
+ type: string
+ post:
+ tags:
+ - Profile
+ description: |
+ Update Profile details of current user
+ **Authorization** All topcoder members are allowed.
+ security:
+ - bearerAuth: []
+ requestBody:
+ content:
+ multipart/form-data:
+ schema:
+ $ref: "#/components/schemas/ProfileUpdate"
+ responses:
+ "204":
+ description: OK
+ "400":
+ description: Bad request
+ content:
+ application/json:
+ schema:
+ oneOf:
+ - $ref: "#/components/schemas/JoiError"
+ - $ref: "#/components/schemas/Error"
+ "401":
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/AuthError"
+ "403":
+ description: Forbidden
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/AuthError"
+ "404":
+ description: Not Found
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Error"
+ "500":
+ description: Internal Server Error
+ content:
+ text/plain::
+ schema:
+ type: string
+components:
+ securitySchemes:
+ bearerAuth:
+ type: http
+ scheme: bearer
+ bearerFormat: JWT
+ schemas:
+ Profile:
+ required:
+ - availability
+ properties:
+ phone:
+ type: string
+ description: "The phone number of the user"
+ example: "+1123226666"
+ resume:
+ type: string
+ description: "The resume of the user"
+ availability:
+ type: boolean
+ description: "The availability of the user"
+ default: true
+ example: true
+ skill:
+ type: string
+ description: "The candidate's skills separated via ,"
+ example: "Java,Angular,SQL Server,JavaScript"
+ salaryExpectation:
+ type: integer
+ description: "The candidate expected salary"
+ hasProfile:
+ type: boolean
+ description: "Whether has profile for the user"
+ ProfileUpdate:
+ required:
+ - phone
+ - availability
+ - city
+ - countryName
+ properties:
+ phone:
+ type: string
+ description: "The phone number of the user"
+ example: "(123) 456-7890"
+ city:
+ type: string
+ description: "The member's city"
+ countryName:
+ type: string
+ description: "The member's country"
+ resume:
+ type: string
+ format: binary
+ description: "The resume file of the user"
+ availability:
+ type: boolean
+ description: "The availability of the user"
+ example: true
+ Error:
+ properties:
+ error:
+ type: boolean
+ example: true
+ status:
+ type: integer
+ example: 404
+ url:
+ type: string
+ format: uri
+ errObj:
+ type: object
+ JoiError:
+ required:
+ - message
+ properties:
+ message:
+ type: string
+ AuthError:
+ properties:
+ version:
+ type: string
+ result:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: false
+ status:
+ type: integer
+ example: 403
+ content:
+ type: object
+ properties:
+ message:
+ type: string
diff --git a/package.json b/package.json
index 3ed6237f7a..45c9302fe6 100644
--- a/package.json
+++ b/package.json
@@ -33,8 +33,8 @@
},
"homepage": "https://github.com/topcoder-platform/community-app#readme",
"engines": {
- "node": "^10.24.1",
- "npm": "^6.14.12"
+ "node": "^8.11.2",
+ "npm": "^5.6.0"
},
"dependencies": {
"@hapi/joi": "^16.1.4",
@@ -172,8 +172,7 @@
"url-parse": "^1.4.1",
"uuid": "^3.3.2",
"valid-url": "^1.0.9",
- "xml2json": "^0.11.2",
- "xss": "^1.0.15"
+ "xml2json": "^0.11.2"
},
"devDependencies": {
"@commitlint/cli": "^8.3.5",
diff --git a/src/server/index.js b/src/server/index.js
index 3ee3671a78..393a72b9a7 100644
--- a/src/server/index.js
+++ b/src/server/index.js
@@ -22,12 +22,14 @@ import { factory as reducerFactory } from 'reducers';
import { redux, server as serverFactory } from 'topcoder-react-utils';
import { getRates as getExchangeRates } from 'services/money';
import { toJson as xmlToJson } from 'utils/xml2json';
-import { promisify } from 'util';
import cdnRouter from './routes/cdn';
+import mailChimpRouter from './routes/mailchimp';
import mockDocuSignFactory from './__mocks__/docu-sign-mock';
import recruitCRMRouter from './routes/recruitCRM';
import mmLeaderboardRouter from './routes/mmLeaderboard';
+import gSheetsRouter from './routes/gSheet';
+import blogRouter from './routes/blog';
import feedsRouter from './routes/feeds';
/* Dome API for topcoder communities */
@@ -40,40 +42,9 @@ global.atob = atob;
const CMS_BASE_URL = `https://app.contentful.com/spaces/${config.SECRET.CONTENTFUL.SPACE_ID}`;
-const getTimestamp = async () => {
- let timestamp;
- try {
- const filePath = path.resolve(__dirname, '../../.build-info');
- if (!filePath.startsWith(path.resolve(__dirname, '../../'))) {
- throw new Error('Invalid file path detected');
- }
-
- const MAX_FILE_SIZE = 10 * 1024; // 10 KB max file size
- const stats = await promisify(fs.stat)(filePath);
- if (stats.size > MAX_FILE_SIZE) {
- throw new Error('File is too large and may cause DoS issues');
- }
-
- const fileContent = await promisify(fs.readFile)(filePath, 'utf-8');
-
- let tsData;
- try {
- tsData = JSON.parse(fileContent);
- } catch (parseErr) {
- throw new Error('Invalid JSON format in file');
- }
-
- if (!tsData || !tsData.timestamp) {
- throw new Error('Timestamp is missing in the JSON file');
- }
-
- timestamp = moment(tsData.timestamp).valueOf();
- } catch (err) {
- console.error('Error:', err.message);
- }
-
- return timestamp;
-};
+let ts = path.resolve(__dirname, '../../.build-info');
+ts = JSON.parse(fs.readFileSync(ts));
+ts = moment(ts.timestamp).valueOf();
const sw = `sw.js${process.env.NODE_ENV === 'production' ? '' : '?debug'}`;
const swScope = '/challenges'; // we are currently only interested in improving challenges pages
@@ -81,7 +52,7 @@ const swScope = '/challenges'; // we are currently only interested in improving
const tcoPattern = new RegExp(/^tco\d{2}\.topcoder(?:-dev)?\.com$/i);
const universalNavUrl = config.UNIVERSAL_NAV_URL;
-const getExtraScripts = ts => [
+const EXTRA_SCRIPTS = [
`