diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..4fea1158 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,85 @@ +version: 2 +jobs: + test: + docker: + - image: circleci/node:8.9.4 + - image: circleci/postgres:9.6.2-alpine + environment: + - POSTGRES_USER: circle_test + - POSTGRES_DB: circle_test + - image: elasticsearch:2.3 + environment: + DB_MASTER_URL: postgres://circle_test:@127.0.0.1:5432/circle_test + AUTH_SECRET: secret + AUTH_DOMAIN: topcoder-dev.com + LOG_LEVEL: debug + APP_VERSION: v4 + steps: + - checkout + - restore_cache: + key: test-node-modules-{{ checksum "package.json" }} + - run: npm install + - save_cache: + key: test-node-modules-{{ checksum "package.json" }} + paths: + - node_modules + - run: npm run lint + - run: npm run test + - run: npm run build + - persist_to_workspace: + root: . + paths: + - dist + deployDev: + docker: + - image: docker:17.06.1-ce-git + steps: + - checkout + - setup_remote_docker + - run: + name: Installation of build dependencies. + command: apk add --no-cache bash + - attach_workspace: + at: ./workspace + - run: + name: Installing AWS client + command: | + apk add --no-cache jq py-pip sudo + sudo pip install awscli --upgrade + - run: ./build.sh DEV + - run: ./deploy.sh DEV + deployProd: + docker: + - image: docker:17.06.1-ce-git + steps: + - checkout + - setup_remote_docker + - run: + name: Installation of build dependencies. + command: apk add --no-cache bash + - attach_workspace: + at: ./workspace + - run: + name: Installing AWS client + command: | + apk add --no-cache jq py-pip sudo + sudo pip install awscli --upgrade + - run: ./build.sh PROD + - run: ./deploy.sh PROD +workflows: + version: 2 + build: + jobs: + - test + - deployDev: + requires: + - test + filters: + branches: + only: dev + - deployProd: + requires: + - test + filters: + branches: + only: 'master' diff --git a/.ebextensions/01-environment-variables.config b/.ebextensions/01-environment-variables.config index ded02ed4..8d8d7ffc 100644 --- a/.ebextensions/01-environment-variables.config +++ b/.ebextensions/01-environment-variables.config @@ -32,9 +32,6 @@ option_settings: - namespace: aws:elasticbeanstalk:application:environment option_name: DIRECT_PROJECT_SERVICE_ENDPOINT value: TBD - - namespace: aws:elasticbeanstalk:application:environment - option_name: TOPIC_SERVICE_ENDPOINT - value: TBD - namespace: aws:elasticbeanstalk:application:environment option_name: FILE_SERVICE_ENDPOINT value: TBD @@ -53,27 +50,6 @@ option_settings: - namespace: aws:elasticbeanstalk:application:environment option_name: AWS_SECRET_ACCESS_KEY value: TBD - - namespace: aws:elasticbeanstalk:application:environment - option_name: SALESFORCE_WEB_TO_LEAD_URL - value: https://www.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8 - - namespace: aws:elasticbeanstalk:application:environment - option_name: SALESFORCE_ORG_ID - value: TBD - - namespace: aws:elasticbeanstalk:application:environment - option_name: SALESFORCE_LEAD_PROJECT_NAME - value: TBD - - namespace: aws:elasticbeanstalk:application:environment - option_name: SALESFORCE_LEAD_PROJECT_DESC - value: TBD - - namespace: aws:elasticbeanstalk:application:environment - option_name: SALESFORCE_LEAD_PROJECT_LINK - value: TBD - - namespace: aws:elasticbeanstalk:application:environment - option_name: SALESFORCE_LEAD_PROJECT_ID - value: TBD - namespace: aws:elasticbeanstalk:application:environment option_name: CONNECT_PROJECTS_URL value: TBD - - namespace: aws:elasticbeanstalk:application:environment - option_name: USER_SERVICE_URL - value: TBD diff --git a/Dockerfile b/Dockerfile index 2a7fe789..8c947c22 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,18 +2,6 @@ FROM node:6.9.4 LABEL version="1.0" LABEL description="Projects microservice" -RUN apt-get update && \ - apt-get upgrade -y - -# install aws -RUN apt-get install -y \ - ssh \ - python \ - python-dev \ - python-pip - -RUN pip install awscli - RUN apt-get install libpq-dev # Create app directory RUN mkdir -p /usr/src/app diff --git a/build.sh b/build.sh new file mode 100755 index 00000000..6e97ae07 --- /dev/null +++ b/build.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +# more bash-friendly output for jq +JQ="jq --raw-output --exit-status" + +ENV=$1 +AWS_REGION=$(eval "echo \$${ENV}_AWS_REGION") +ACCOUNT_ID=$(eval "echo \$${ENV}_AWS_ACCOUNT_ID") +AWS_REPOSITORY=$(eval "echo \$${ENV}_AWS_REPOSITORY") + +build() { + docker build -t $ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$AWS_REPOSITORY:$CIRCLE_SHA1 . +} + +build \ No newline at end of file diff --git a/circle.yml b/circle.yml deleted file mode 100644 index ddc060f3..00000000 --- a/circle.yml +++ /dev/null @@ -1,55 +0,0 @@ -machine: - - node: - version: v6.9.4 - environment: - DB_MASTER_URL: postgres://ubuntu:@127.0.0.1:5432/circle_test - #RABBITMQ_URL: amqp://localhost:5672 - AUTH_SECRET: secret - AUTH_DOMAIN: topcoder-dev.com - LOG_LEVEL: debug - APP_VERSION: v4 - -dependencies: - pre: - - pip install awsebcli - override: - - npm install - - wget https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/2.3.5/elasticsearch-2.3.5.tar.gz - - tar -xvf elasticsearch-2.3.5.tar.gz - - elasticsearch-2.3.5/bin/elasticsearch: {background: true} - # Make sure that Elasticsearch is up before running tests: - - sleep 10 && wget --waitretry=5 --retry-connrefused -v http://127.0.0.1:9200/ - - -deployment: - development: - branch: [dev, 'feature/admin-endpoints'] - commands: - - ./ebs_deploy.sh tc-project-service DEV $CIRCLE_BUILD_NUM - - - production: - branch: master - commands: - - ./ebs_deploy.sh tc-project-service PROD $CIRCLE_BUILD_NUM - - # tag: /v[0-9]+(\.[0-9]+)*/ - # owner: appirio-tech - # commands: - # - ./ebs_deploy.sh tc-project-service PROD $CIRCLE_TAG - -general: - artifacts: - - ./coverage - -notify: - webhooks: - # slack - product-dev - - url: https://hooks.slack.com/services/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 - -experimental: - notify: - branches: - only: - - master diff --git a/config/custom-environment-variables.json b/config/custom-environment-variables.json index 59ff0ddd..40b5c6b8 100644 --- a/config/custom-environment-variables.json +++ b/config/custom-environment-variables.json @@ -1,4 +1,5 @@ { + "apiVersion": "API_VERSION", "authSecret": "AUTH_SECRET", "logLevel": "LOG_LEVEL", "version": "APP_VERSION", @@ -17,26 +18,16 @@ "directProjectServiceTimeout": "DIRECT_PROJECT_SERVICE_TIMEOUt", "fileServiceEndpoint": "FILE_SERVICE_ENDPOINT", "identityServiceEndpoint": "IDENTITY_SERVICE_ENDPOINT", - "topicServiceEndpoint": "TOPIC_SERVICE_ENDPOINT", "memberServiceEndpoint": "MEMBER_SERVICE_ENDPOINT", "systemUserClientId": "SYSTEM_USER_CLIENT_ID", "systemUserClientSecret": "SYSTEM_USER_CLIENT_SECRET", - "userServiceUrl": "USER_SERVICE_URL", "connectProjectsUrl": "CONNECT_PROJECTS_URL", - "salesforceLead" : { - "webToLeadUrl": "SALESFORCE_WEB_TO_LEAD_URL", - "orgId" : "SALESFORCE_ORG_ID", - "projectNameFieldId": "SALESFORCE_LEAD_PROJECT_NAME", - "projectDescFieldId": "SALESFORCE_LEAD_PROJECT_DESC", - "projectLinkFieldId": "SALESFORCE_LEAD_PROJECT_LINK", - "projectIdFieldId" : "SALESFORCE_LEAD_PROJECT_ID" - }, "dbConfig": { "masterUrl": "DB_MASTER_URL", "maxPoolSize": "DB_MAX_POOL_SIZE", "minPoolSize": "DB_MIN_POOL_SIZE" }, - "analyticsKey": "ANALYTICS_KEY", + "analyticsKey": "SEGMENT_ANALYTICS_KEY", "validIssuers": "VALID_ISSUERS", "jwksUri": "JWKS_URI", "busApiUrl": "BUS_API_URL", diff --git a/config/default.json b/config/default.json index 167c89b5..2358f4a0 100644 --- a/config/default.json +++ b/config/default.json @@ -1,4 +1,5 @@ { + "apiVersion": "v4", "authSecret": "secret", "authDomain": "topcoder-dev.com", "logLevel": "info", @@ -9,7 +10,6 @@ "pubsubQueueName": "project.service", "pubsubExchangeName": "projects", "fileServiceEndpoint": "", - "topicServiceEndpoint": "", "identityServiceEndpoint": "", "memberServiceEndpoint": "", "directProjectServiceEndpoint": "", @@ -25,16 +25,7 @@ }, "systemUserClientId": "", "systemUserClientSecret": "", - "userServiceUrl": "", "connectProjectUrl":"", - "salesforceLead" : { - "webToLeadUrl": "https://www.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8", - "orgId": "", - "projectNameFieldId": "", - "projectDescFieldId": "", - "projectLinkFieldId": "", - "projectIdFieldId" : "" - }, "dbConfig": { "masterUrl": "", "maxPoolSize": 50, diff --git a/config/sample.local.js b/config/sample.local.js index 47dbc0bd..058f9089 100644 --- a/config/sample.local.js +++ b/config/sample.local.js @@ -12,18 +12,9 @@ if (process.env.NODE_ENV === 'test') { logentriesToken: '', rabbitmqURL: 'amqp://dockerhost:5672', fileServiceEndpoint: 'https://api.topcoder-dev.com/v3/files/', - topicServiceEndpoint: 'https://api.topcoder-dev.com/v4/topics/', directProjectServiceEndpoint: 'https://api.topcoder-dev.com/v3/direct', connectProjectsUrl: 'https://connect.topcoder-dev.com/projects/', memberServiceEndpoint: 'http://dockerhost:3001/members', - salesforceLead: { - webToLeadUrl: 'https://www.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8', - orgId: '00D2C0000000dO6', - projectNameFieldId: 'title', - projectDescFieldId: 'description', - projectLinkFieldId: 'URL', - projectIdFieldId: '00N2C000000Vxxx', - }, dbConfig: { masterUrl: 'postgres://coder:mysecretpassword@dockerhost:54321/projectsdb', maxPoolSize: 50, diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 00000000..628a634e --- /dev/null +++ b/deploy.sh @@ -0,0 +1,243 @@ +#!/usr/bin/env bash + +# more bash-friendly output for jq +JQ="jq --raw-output --exit-status" + +ENV=$1 +COUNTER_LIMIT=20 +ACCOUNT_ID=$(eval "echo \$${ENV}_AWS_ACCOUNT_ID") +AWS_REGION=$(eval "echo \$${ENV}_AWS_REGION") +AWS_ECS_CONTAINER_NAME="tc-project-service" +AWS_REPOSITORY=$(eval "echo \$${ENV}_AWS_REPOSITORY") +AWS_ECS_CLUSTER=$(eval "echo \$${ENV}_AWS_ECS_CLUSTER") +AWS_ECS_SERVICE=$(eval "echo \$${ENV}_AWS_ECS_SERVICE") +AUTH_DOMAIN=$(eval "echo \$${ENV}_AUTH_DOMAIN") +AUTH_SECRET=$(eval "echo \$${ENV}_AUTH_SECRET") +VALID_ISSUERS=$(eval "echo \$${ENV}_VALID_ISSUERS") +PORT=3000 +family="tc-project-service" + +# configures aws cli for further usage +configure_aws_cli() { + export AWS_ACCESS_KEY_ID=$(eval "echo \$${ENV}_AWS_ACCESS_KEY_ID") + export AWS_SECRET_ACCESS_KEY=$(eval "echo \$${ENV}_AWS_SECRET_ACCESS_KEY") + aws --version + aws configure set default.region $AWS_REGION + aws configure set default.output json +} + +# deploys the app to the ecs cluster +deploy_cluster() { + + make_task_def + register_definition + if [[ $(aws ecs update-service --cluster $AWS_ECS_CLUSTER --service $AWS_ECS_SERVICE --task-definition $revision | \ + $JQ '.service.taskDefinition') != $revision ]]; then + echo "Error updating service." + return 1 + fi + + echo "Deployed!" + return 0 +} + +make_task_def(){ + task_template='{ + "family": "%s", + "requiresCompatibilities": ["EC2", "FARGATE"], + "networkMode": "awsvpc", + "executionRoleArn": "arn:aws:iam::%s:role/ecsTaskExecutionRole", + "cpu": "1024", + "memory": "2048", + "containerDefinitions": [ + { + "name": "%s", + "image": "%s.dkr.ecr.%s.amazonaws.com/%s:%s", + "essential": true, + "memory": 200, + "cpu": 10, + "environment": [ + { + "name": "NODE_ENV", + "value": "%s" + }, + { + "name": "LOG_LEVEL", + "value": "%s" + }, + { + "name": "CAPTURE_LOGS", + "value": "%s" + }, + { + "name": "LOGENTRIES_TOKEN", + "value": "%s" + }, + { + "name": "API_VERSION", + "value": "%s" + }, + { + "name": "AWS_REGION", + "value": "%s" + }, + { + "name": "AWS_ACCESS_KEY_ID", + "value": "%s" + }, + { + "name": "AWS_SECRET_ACCESS_KEY", + "value": "%s" + }, + { + "name": "AUTH_DOMAIN", + "value": "%s" + }, + { + "name": "AUTH_SECRET", + "value": "%s" + }, + { + "name": "VALID_ISSUERS", + "value": "%s" + }, + { + "name": "DB_MASTER_URL", + "value": "%s" + }, + { + "name": "MEMBER_SERVICE_ENDPOINT", + "value": "%s" + }, + { + "name": "IDENTITY_SERVICE_ENDPOINT", + "value": "%s" + }, + { + "name": "BUS_API_URL", + "value": "%s" + }, + { + "name": "BUS_API_TOKEN", + "value": "%s" + }, + { + "name": "SYSTEM_USER_CLIENT_ID", + "value": "%s" + }, + { + "name": "SYSTEM_USER_CLIENT_SECRET", + "value": "%s" + }, + { + "name": "PROJECTS_ES_URL", + "value": "%s" + }, + { + "name": "PROJECTS_ES_INDEX_NAME", + "value": "%s" + }, + { + "name": "RABBITMQ_URL", + "value": "%s" + }, + { + "name": "DIRECT_PROJECT_SERVICE_ENDPOINT", + "value": "%s" + }, + { + "name": "FILE_SERVICE_ENDPOINT", + "value": "%s" + }, + { + "name": "CONNECT_PROJECTS_URL", + "value": "%s" + }, + { + "name": "SEGMENT_ANALYTICS_KEY", + "value": "%s" + } + ], + "portMappings": [ + { + "hostPort": %s, + "protocol": "tcp", + "containerPort": %s + } + ], + "logConfiguration": { + "logDriver": "awslogs", + "options": { + "awslogs-group": "/aws/ecs/%s", + "awslogs-region": "%s", + "awslogs-stream-prefix": "%s" + } + } + } + ]}' + API_VERSION=$(eval "echo \$${ENV}_API_VERSION") + DB_MASTER_URL=$(eval "echo \$${ENV}_DB_MASTER_URL") + MEMBER_SERVICE_ENDPOINT=$(eval "echo \$${ENV}_MEMBER_SERVICE_ENDPOINT") + IDENTITY_SERVICE_ENDPOINT=$(eval "echo \$${ENV}_IDENTITY_SERVICE_ENDPOINT") + BUS_API_URL=$(eval "echo \$${ENV}_BUS_API_URL") + BUS_API_TOKEN=$(eval "echo \$${ENV}_BUS_API_TOKEN") + SYSTEM_USER_CLIENT_ID=$(eval "echo \$${ENV}_SYSTEM_USER_CLIENT_ID") + SYSTEM_USER_CLIENT_SECRET=$(eval "echo \$${ENV}_SYSTEM_USER_CLIENT_SECRET") + CAPTURE_LOGS=$(eval "echo \$${ENV}_CAPTURE_LOGS") + LOGENTRIES_TOKEN=$(eval "echo \$${ENV}_LOGENTRIES_TOKEN") + LOG_LEVEL=$(eval "echo \$${ENV}_LOG_LEVEL") + PROJECTS_ES_URL=$(eval "echo \$${ENV}_PROJECTS_ES_URL") + PROJECTS_ES_INDEX_NAME=$(eval "echo \$${ENV}_PROJECTS_ES_INDEX_NAME") + RABBITMQ_URL=$(eval "echo \$${ENV}_RABBITMQ_URL") + DIRECT_PROJECT_SERVICE_ENDPOINT=$(eval "echo \$${ENV}_DIRECT_PROJECT_SERVICE_ENDPOINT") + FILE_SERVICE_ENDPOINT=$(eval "echo \$${ENV}_FILE_SERVICE_ENDPOINT") + CONNECT_PROJECTS_URL=$(eval "echo \$${ENV}_CONNECT_PROJECTS_URL") + SEGMENT_ANALYTICS_KEY=$(eval "echo \$${ENV}_SEGMENT_ANALYTICS_KEY") + if [ "$ENV" = "PROD" ]; then + NODE_ENV=production + elif [ "$ENV" = "DEV" ]; then + NODE_ENV=development + fi + echo "NODE_ENV" + echo $NODE_ENV + + task_def=$(printf "$task_template" $family $ACCOUNT_ID $AWS_ECS_CONTAINER_NAME $ACCOUNT_ID $AWS_REGION $AWS_REPOSITORY $CIRCLE_SHA1 $NODE_ENV $LOG_LEVEL $CAPTURE_LOGS $LOGENTRIES_TOKEN $API_VERSION $AWS_REGION $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY $AUTH_DOMAIN $AUTH_SECRET $VALID_ISSUERS $DB_MASTER_URL $MEMBER_SERVICE_ENDPOINT $IDENTITY_SERVICE_ENDPOINT $BUS_API_URL $BUS_API_TOKEN $SYSTEM_USER_CLIENT_ID $SYSTEM_USER_CLIENT_SECRET $PROJECTS_ES_URL $PROJECTS_ES_INDEX_NAME $RABBITMQ_URL $DIRECT_PROJECT_SERVICE_ENDPOINT $FILE_SERVICE_ENDPOINT $CONNECT_PROJECTS_URL $SEGMENT_ANALYTICS_KEY $PORT $PORT $AWS_ECS_CLUSTER $AWS_REGION $NODE_ENV) +} + +push_ecr_image(){ + eval $(aws ecr get-login --region $AWS_REGION --no-include-email) + docker push $ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$AWS_REPOSITORY:$CIRCLE_SHA1 +} + +register_definition() { + if revision=$(aws ecs register-task-definition --cli-input-json "$task_def" 2> /dev/null | $JQ '.taskDefinition.taskDefinitionArn'); then + echo "Revision: $revision" + else + echo "Failed to register task definition" + return 1 + fi +} + +check_service_status() { + counter=0 + sleep 60 + servicestatus=`aws ecs describe-services --service $AWS_ECS_SERVICE --cluster $AWS_ECS_CLUSTER | $JQ '.services[].events[0].message'` + while [[ $servicestatus != *"steady state"* ]] + do + echo "Current event message : $servicestatus" + echo "Waiting for 30 seconds to check the service status...." + sleep 30 + servicestatus=`aws ecs describe-services --service $AWS_ECS_SERVICE --cluster $AWS_ECS_CLUSTER | $JQ '.services[].events[0].message'` + counter=`expr $counter + 1` + if [[ $counter -gt $COUNTER_LIMIT ]] ; then + echo "Service does not reach steady state within 10 minutes. Please check" + exit 1 + fi + done + echo "$servicestatus" +} + +configure_aws_cli +push_ecr_image +deploy_cluster +check_service_status \ No newline at end of file diff --git a/ebs_deploy.sh b/ebs_deploy.sh deleted file mode 100755 index 94e9af47..00000000 --- a/ebs_deploy.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -SERVICE=$1 -ENV=$2 -TAG_SUFFIX=$3 -TAG="$ENV.$TAG_SUFFIX" -ENV_LOWER=`echo "$ENV" | awk '{print tolower($0)}'` - -echo "Deploying to Elasticbeanstalk" -echo "############################" -export AWS_ACCESS_KEY_ID=$(eval "echo \$${ENV}_AWS_ACCESS_KEY_ID") -export AWS_SECRET_ACCESS_KEY=$(eval "echo \$${ENV}_AWS_SECRET_ACCESS_KEY") - -# eb deploy -# eb init -r us-east-1 $SERVICE -EB_OUTPUT="$(eb deploy tc-project-api-v4-${ENV_LOWER} -l $TAG -r us-east-1)" - -echo $EB_OUTPUT -if echo $EB_OUTPUT | grep -iq error; then - exit 1 -fi -exit 0 diff --git a/src/app.js b/src/app.js index dbb693ca..864fb0e6 100644 --- a/src/app.js +++ b/src/app.js @@ -4,6 +4,7 @@ import _ from 'lodash'; import bodyParser from 'body-parser'; import expressSanitizer from 'express-sanitizer'; import config from 'config'; +import cors from 'cors'; import coreLib from 'tc-core-library-js'; import expressRequestId from 'express-request-id'; import router from './routes'; @@ -63,6 +64,20 @@ const logger = coreLib.logger({ app.use(coreLib.middleware.logger(null, logger)); app.logger = logger; +// ======================= +// CORS ================ +// ======================= +// const whitelist = [`*.${domain}`]; +// const corsOptions = { +// origin: (origin, callback) => { +// const originIsWhitelisted = whitelist.indexOf(origin) !== -1; +// callback(null, originIsWhitelisted); +// }, +// }; +// app.use(cors(corsOptions)); +// app.options('*', cors()); +app.use(cors()); + // ======================= // Database ========= // ======================= diff --git a/src/routes/index.js b/src/routes/index.js index 16018aef..47a51502 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -1,10 +1,13 @@ import _ from 'lodash'; +import config from 'config'; import validate from 'express-validation'; import { Router } from 'express'; const router = Router(); +const apiVersion = config.apiVersion; + validate.options({ status: 422, flatten: true, @@ -12,7 +15,7 @@ validate.options({ }); // health check -router.get('/_health', (req, res) => { +router.get(`/${apiVersion}/projects/health`, (req, res) => { // TODO more checks res.status(200).send({ message: 'All-is-well', @@ -23,7 +26,7 @@ router.get('/_health', (req, res) => { // All project service endpoints need authentication const jwtAuth = require('tc-core-library-js').middleware.jwtAuthenticator; -router.all('/v4/projects*', jwtAuth()); +router.all(RegExp(`\\/${apiVersion}\\/projects(?!\\/health).*`), jwtAuth()); // Register all the routes router.route('/v4/projects') diff --git a/src/routes/projects/create.js b/src/routes/projects/create.js index 684ef859..23ddaccd 100644 --- a/src/routes/projects/create.js +++ b/src/routes/projects/create.js @@ -118,6 +118,7 @@ module.exports = [ if (newProject.billingAccountId) { body.billingAccountId = newProject.billingAccountId; } + req.log.debug('creating project history for project %d', newProject.id); // add to project history models.ProjectHistory.create({ projectId: _newProject.id, @@ -125,6 +126,7 @@ module.exports = [ cancelReason: null, updatedBy: req.authUser.userId, }); + req.log.debug('creating direct project for project %d', newProject.id); return directProject.createDirectProject(req, body) .then((resp) => { newProject.directProjectId = resp.data.result.content.projectId; @@ -139,17 +141,18 @@ module.exports = [ }); // return Promise.resolve(); }) - .then(() => { newProject = newProject.get({ plain: true }); // remove utm details & deletedAt field newProject = _.omit(newProject, ['deletedAt', 'utm']); // add an empty attachments array newProject.attachments = []; + req.log.debug('Sending event to RabbitMQ bus for project %d', newProject.id); req.app.services.pubsub.publish(EVENT.ROUTING_KEY.PROJECT_DRAFT_CREATED, newProject, { correlationId: req.id }, ); + req.log.debug('Sending event to Kafka bus for project %d', newProject.id); // emit event req.app.emit(EVENT.ROUTING_KEY.PROJECT_DRAFT_CREATED, { req, project: newProject }); res.status(201).json(util.wrapResponse(req.id, newProject, 1, 201)); diff --git a/src/routes/projects/list.js b/src/routes/projects/list.js index f1cd2c9a..d2ffa319 100755 --- a/src/routes/projects/list.js +++ b/src/routes/projects/list.js @@ -133,6 +133,23 @@ const parseElasticSearchCriteria = (criteria, fields, order) => { }, }, }, + { + nested: { + path: 'details', + query: { + nested: { + path: 'details.utm', + query: { + query_string: { + query: `*${keyword}*`, + analyze_wildcard: true, + fields: ['details.utm.code'], + }, + }, + }, + }, + }, + }, ], }, }; diff --git a/src/services/topicService.js b/src/services/topicService.js deleted file mode 100644 index 204f07bf..00000000 --- a/src/services/topicService.js +++ /dev/null @@ -1,53 +0,0 @@ -import config from 'config'; -import util from '../util'; -/** - * Service methods to handle creating topics - */ - -/** - * Build custom http client for request - * @param {Object} req request - * @returns {Promise} custom http client - * @private - */ -function getHttpClient(req) { - const httpClient = util.getHttpClient(req); - httpClient.defaults.headers.common.Authorization = req.headers.authorization; - httpClient.defaults.baseURL = config.get('topicServiceEndpoint'); - httpClient.defaults.timeout = 30000; - httpClient.interceptors.response.use((resp) => { - // req.log.debug('resp: ', JSON.stringify(resp.data, null, 2)) - if (resp.status !== 200 || resp.data.result.status !== 200) { - // req.log.error('error resp: ', JSON.stringify(resp.data, null, 2)) - return Promise.reject(new Error(resp.data.result.content.message)); - } - return Promise.resolve(resp); - }); - return httpClient; -} - - -/** - * Create topics in topic service - * @param {Object} req request object - * @param {integer} projectId project id - * @param {String} title title of the post - * @param {String} message message to be posted - * @param {String} tag tag, defaults to PRIMARY - * @return {Promise} returned Promise - */ -function createTopic(req, projectId, title, message, tag = 'PRIMARY') { - return getHttpClient(req) - .post('', { - reference: 'project', - referenceId: projectId.toString(), - tag, - title, - body: message, - }); -} - - -export default { - createTopic, -}; diff --git a/src/util.js b/src/util.js index 6371f726..86386add 100644 --- a/src/util.js +++ b/src/util.js @@ -264,7 +264,7 @@ _.assignIn(util, { httpClient.defaults.headers.common.Accept = 'application/json'; httpClient.defaults.headers.common['Content-Type'] = 'application/json'; httpClient.defaults.headers.common.Authorization = `Bearer ${jwtToken}`; - return httpClient.get(`${config.userServiceUrl}/${userId}`).then((response) => { + return httpClient.get(`${config.identityServiceEndpoint}users/${userId}`).then((response) => { if (response.data && response.data.result && response.data.result.status === 200 && response.data.result.content) { return response.data.result.content;