diff --git a/README.md b/README.md index 2e0a3c2..0bd5b64 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ Note: heroku domain should match subdomain of topcoder-dev or topcoder depending ## Verification -- run `npm serve` to start the app +- run `npm run serve` to start the app - 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. - go to settings by clicking username at top right corner - setup both git provider to authorize topcoder-x to manage your repo on behalf of you diff --git a/package-lock.json b/package-lock.json index 986a2de..1a1b260 100644 --- a/package-lock.json +++ b/package-lock.json @@ -207,6 +207,11 @@ } } }, + "@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" + }, "@types/node": { "version": "6.0.111", "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.111.tgz", @@ -666,8 +671,7 @@ "assertion-error": { "version": "1.0.2", "resolved": "http://registry.npm.taobao.org/assertion-error/download/assertion-error-1.0.2.tgz", - "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", - "dev": true + "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=" }, "assign-symbols": { "version": "1.0.0", @@ -2013,8 +2017,7 @@ "browser-stdout": { "version": "1.3.0", "resolved": "http://registry.npm.taobao.org/browser-stdout/download/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=" }, "browser-sync": { "version": "2.18.13", @@ -2912,6 +2915,27 @@ "unset-value": "^1.0.0" } }, + "cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + } + } + }, "caller-path": { "version": "0.1.0", "resolved": "http://registry.npm.taobao.org/caller-path/download/caller-path-0.1.0.tgz", @@ -2980,7 +3004,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", - "dev": true, "requires": { "assertion-error": "^1.0.1", "check-error": "^1.0.1", @@ -3058,8 +3081,7 @@ "check-error": { "version": "1.0.2", "resolved": "http://registry.npm.taobao.org/check-error/download/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" }, "chokidar": { "version": "1.7.0", @@ -3207,6 +3229,14 @@ "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", "dev": true }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "^1.0.0" + } + }, "clone-stats": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", @@ -3385,8 +3415,7 @@ "commander": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", - "dev": true + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" }, "commondir": { "version": "0.0.1", @@ -3860,14 +3889,20 @@ "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, "requires": { "type-detect": "^4.0.0" } @@ -4253,6 +4288,11 @@ } } }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, "duplexify": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", @@ -6034,6 +6074,20 @@ "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", "dev": true }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-copy-file-sync": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fs-copy-file-sync/-/fs-copy-file-sync-1.1.1.tgz", + "integrity": "sha512-2QY5eeqVv4m2PfyMiEuy9adxNP+ajf+8AR05cEi+OAzPcOj90hvFImeZhTmKLBgSd9EvG33jsD7ZRxsx9dThkQ==" + }, "fs-exists-sync": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", @@ -6043,8 +6097,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "http://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "1.2.4", @@ -6617,8 +6670,7 @@ "get-func-name": { "version": "2.0.0", "resolved": "http://registry.npm.taobao.org/get-func-name/download/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" }, "get-parameter-names": { "version": "0.3.0", @@ -6631,6 +6683,11 @@ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -6766,7 +6823,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7063,6 +7119,37 @@ "sparkles": "^1.0.0" } }, + "got": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.1.tgz", + "integrity": "sha512-tiLX+bnYm5A56T5N/n9Xo89vMaO1mrS9qoDqj3u/anVooqGozvY/HbXzEpDfbNeKsHCBpK40gSbz8wGYSp3i1w==", + "requires": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, "graceful-fs": { "version": "4.1.11", "resolved": "http://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.1.11.tgz", @@ -9511,6 +9598,19 @@ "escape-string-regexp": "^1.0.3" } }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "requires": { + "has-symbol-support-x": "^1.4.1" + } + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -9593,6 +9693,11 @@ "sntp": "1.x.x" } }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -9657,6 +9762,11 @@ } } }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" + }, "http-errors": { "version": "1.6.2", "resolved": "http://registry.npm.taobao.org/http-errors/download/http-errors-1.6.2.tgz", @@ -9777,7 +9887,6 @@ "version": "1.0.6", "resolved": "http://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -10031,6 +10140,15 @@ "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", "dev": true }, + "into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", + "requires": { + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" + } + }, "invariant": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", @@ -10254,6 +10372,11 @@ "lodash.isfinite": "^3.3.2" } }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" + }, "is-odd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", @@ -10295,6 +10418,11 @@ "path-is-inside": "^1.0.1" } }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -10363,6 +10491,11 @@ "tryit": "^1.0.1" } }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -10443,6 +10576,15 @@ "textextensions": "~1.0.0" } }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } + }, "items": { "version": "2.1.1", "resolved": "http://registry.npm.taobao.org/items/download/items-2.1.1.tgz", @@ -10673,6 +10815,11 @@ } } }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, "json-fallback": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/json-fallback/-/json-fallback-0.0.1.tgz", @@ -10892,6 +11039,14 @@ "resolved": "https://registry.npmjs.org/kareem/-/kareem-1.5.0.tgz", "integrity": "sha1-4+QQHZ3P3imXadr0tNtk2JXRdEg=" }, + "keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "requires": { + "json-buffer": "3.0.0" + } + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -11807,6 +11962,11 @@ "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", "dev": true }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, "lru-cache": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", @@ -12112,6 +12272,11 @@ "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", "dev": true }, + "mimic-response": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz", + "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=" + }, "min-document": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", @@ -12217,7 +12382,6 @@ "version": "0.5.1", "resolved": "http://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" }, @@ -12225,8 +12389,7 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" } } }, @@ -12732,6 +12895,16 @@ "remove-trailing-separator": "^1.0.1" } }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "requires": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + } + }, "number-is-nan": { "version": "1.0.1", "resolved": "http://registry.npm.taobao.org/number-is-nan/download/number-is-nan-1.0.1.tgz", @@ -12897,7 +13070,6 @@ "version": "1.4.0", "resolved": "http://registry.npm.taobao.org/once/download/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -13021,6 +13193,21 @@ "os-tmpdir": "^1.0.0" } }, + "p-cancelable": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==" + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" + }, "p-limit": { "version": "1.1.0", "resolved": "http://registry.npm.taobao.org/p-limit/download/p-limit-1.1.0.tgz", @@ -13036,6 +13223,14 @@ "p-limit": "^1.1.0" } }, + "p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "requires": { + "p-finally": "^1.0.0" + } + }, "pace-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pace-js/-/pace-js-1.0.2.tgz", @@ -13083,6 +13278,68 @@ "pbkdf2": "^3.0.3" } }, + "parse-domain": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.1.2.tgz", + "integrity": "sha512-I1HuHXYL8hZp9MYf0jHZE2nW0qhJnqBAxKOR9sGCbiBoD3znYrp4nh3SH9dkt2+f6gEenEj6sh537FTNe+QBqg==", + "requires": { + "chai": "^4.1.2", + "fs-copy-file-sync": "^1.1.1", + "got": "^8.0.1", + "mkdirp": "^0.5.1", + "mocha": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==" + }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==" + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + }, + "mocha": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + } + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "requires": { + "has-flag": "^2.0.0" + } + } + } + }, "parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", @@ -13258,8 +13515,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "http://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { "version": "1.0.2", @@ -13313,8 +13569,7 @@ "pathval": { "version": "1.1.0", "resolved": "http://registry.npm.taobao.org/pathval/download/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "dev": true + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" }, "pause-stream": { "version": "0.0.11", @@ -13488,6 +13743,11 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", @@ -13702,6 +13962,16 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" }, + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -14372,6 +14642,14 @@ "minimatch": "^3.0.2" } }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "requires": { + "lowercase-keys": "^1.0.0" + } + }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", @@ -14989,6 +15267,14 @@ } } }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "requires": { + "is-plain-obj": "^1.0.0" + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -15390,6 +15676,11 @@ "limiter": "^1.0.5" } }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, "string-length": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz", @@ -15743,6 +16034,11 @@ "os-homedir": "^1.0.0" } }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, "timers-ext": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.5.tgz", @@ -15966,8 +16262,7 @@ "type-detect": { "version": "4.0.3", "resolved": "http://registry.npm.taobao.org/type-detect/download/type-detect-4.0.3.tgz", - "integrity": "sha1-Dj8mcLRAmbC0bChNE2p+9Jx0wuo=", - "dev": true + "integrity": "sha1-Dj8mcLRAmbC0bChNE2p+9Jx0wuo=" }, "type-is": { "version": "1.6.15", @@ -16165,6 +16460,19 @@ "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=" }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "requires": { + "prepend-http": "^2.0.0" + } + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" + }, "use": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", @@ -16760,8 +17068,7 @@ "wrappy": { "version": "1.0.2", "resolved": "http://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { "version": "0.2.1", diff --git a/package.json b/package.json index c5de358..22b53e6 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "mongoose": "^4.11.9", "octonode": "^0.9.2", "pace-js": "~1.0.2", + "parse-domain": "^2.1.2", "shortid": "^2.2.8", "superagent": "^3.6.0", "superagent-promise": "^1.1.0", diff --git a/src/common/helper.js b/src/common/helper.js index f801875..6018a12 100644 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -15,13 +15,16 @@ const getParams = require('get-parameter-names'); const bluebird = require('bluebird'); const uuid = require('uuid/v4'); const bcrypt = require('bcryptjs'); +const parseDomain = require('parse-domain'); const config = require('../config'); const logger = require('./logger'); const errors = require('./errors'); const constants = require('./constants'); const NotFoundError = require('./errors').NotFoundError; +const ValidationError = require('./errors').ValidationError; bluebird.promisifyAll(bcrypt); +bluebird.promisifyAll(parseDomain); /** * Convert array with arguments to object @@ -82,7 +85,7 @@ function _decorateWithValidators(service) { const params = getParams(method); service[name] = async function serviceMethodWithValidation(...args) { const value = _combineObject(params, args); - const normalized = Joi.attempt(value, method.schema, {abortEarly: false}); + const normalized = Joi.attempt(value, method.schema, { abortEarly: false }); // Joi will normalize values // for example string number '1' to 1 // if schema type is number @@ -188,6 +191,42 @@ async function ensureExists(Model, criteria) { return result; } +/** + * get the provider name from git repo url + * @param {String} repoUrl the project repo URL + * @returns {String} the provider + */ +async function getProviderType(repoUrl) { + const parsedDomain = await parseDomain(repoUrl); + if (!parsedDomain || !parsedDomain.domain || (parsedDomain.domain !== 'github' && parsedDomain.domain !== 'gitlab')) { + throw new ValidationError('Invalid git repo url'); + } + return parsedDomain.domain; +} + +/** + * gets the git username of copilot for a project + * @param {Object} models the db models + * @param {Object} project the db project detail + * @param {String} provider the git provider + * @returns {Object} the owner/copilot for the project + */ +async function getProjectOwner(models, project, provider) { + const userMapping = await models.UserMapping.findOne({ + topcoderUsername: project.username, + }); + + if (!userMapping || (provider === 'github' && !userMapping.githubUserId) || (provider === 'gitlab' && !userMapping.gitlabUserId)) { + throw new Error(`Couldn't find owner username for '${provider}' for this repository.`); + } + + const copilot = await models.User.findOne({ + username: provider === 'github' ? userMapping.githubUsername : userMapping.gitlabUsername, + type: provider, + }); + return copilot; +} + /** * Generate an unique identifier @@ -206,4 +245,6 @@ module.exports = { convertGitLabError, ensureExists, generateIdentifier, + getProviderType, + getProjectOwner, }; diff --git a/src/controllers/ProjectController.js b/src/controllers/ProjectController.js index 6f92ad3..acf2d6d 100644 --- a/src/controllers/ProjectController.js +++ b/src/controllers/ProjectController.js @@ -18,7 +18,7 @@ const ProjectService = require('../services/ProjectService'); * @returns {Object} the result */ async function create(req) { - return await ProjectService.create(req.body); + return await ProjectService.create(req.body, req.currentUser.handle); } /** @@ -28,7 +28,7 @@ async function create(req) { * @returns {Object} the result */ async function update(req) { - return await ProjectService.update(req.body); + return await ProjectService.update(req.body, req.currentUser.handle); } /** @@ -37,7 +37,7 @@ async function update(req) { * @returns {Array} the result */ async function getAll(req) { - return await ProjectService.getAll(req.query.status); + return await ProjectService.getAll(req.query.status, req.currentUser.handle); } /** @@ -47,7 +47,7 @@ async function getAll(req) { * @returns {Object} the result */ async function createLabel(req) { - return await ProjectService.createLabel(req.body); + return await ProjectService.createLabel(req.body, req.currentUser.handle); } /** @@ -57,7 +57,7 @@ async function createLabel(req) { * @returns {Object} the result */ async function createHook(req) { - return await ProjectService.createHook(req.body); + return await ProjectService.createHook(req.body, req.currentUser.handle); } module.exports = { diff --git a/src/front/src/.eslintrc b/src/front/src/.eslintrc index b5b619a..5782540 100644 --- a/src/front/src/.eslintrc +++ b/src/front/src/.eslintrc @@ -5,7 +5,10 @@ "rules": { "angular/no-service-method": 0, "angular/window-service": 0, - "angular/di": [2, "array"], + "angular/di": [ + 2, + "array" + ], "angular/angularelement": 0, "angular/timeout-service": 0, "max-params": 0, @@ -14,19 +17,21 @@ "valid-jsdoc": 0, "require-jsdoc": 0, "no-magic-numbers": 0, - "no-invalid-this" : 0, - "no-nested-ternary" : 0, - "no-void" : 0, - "consistent-return" : 0, - "lodash/prefer-includes" : 0, - "one-var" : 0, - "no-restricted-syntax" : 0, - "func-style" : 0, - "vars-on-top" : 0, - "func-names" : 0, - "prefer-rest-params" : 0, - "no-var":0, - "no-inner-declarations":0 + "no-invalid-this": 0, + "no-nested-ternary": 0, + "no-void": 0, + "consistent-return": 0, + "lodash/prefer-includes": 0, + "one-var": 0, + "no-restricted-syntax": 0, + "func-style": 0, + "vars-on-top": 0, + "func-names": 0, + "prefer-rest-params": 0, + "no-var": 0, + "no-inner-declarations": 0, + "prefer-arrow-callback": 0, + "prefer-template":0, }, "env": { "browser": true, @@ -34,4 +39,4 @@ "es6": true, "jquery": true } -} +} \ No newline at end of file diff --git a/src/front/src/app/projects/projects.html b/src/front/src/app/projects/projects.html index 53ce9ef..2b7f14d 100644 --- a/src/front/src/app/projects/projects.html +++ b/src/front/src/app/projects/projects.html @@ -42,7 +42,7 @@ <h4>You don't have active projects right now. Please </tr> </thead> <tbody> - <tr ng-repeat="project in projects" class="animate-repeat" ng-class-even="'footable-even'" ng-class-odd="'footable-odd'"> + <tr ng-repeat="project in projects" ng-class-even="'footable-even'" ng-class-odd="'footable-odd'"> <td class="col-lg-2">{{project.title}}</td> <td class="col-lg-2"> <a href="{{directUrlBase}}{{project.tcDirectId}}" target="_blank">{{project.tcDirectId}}</a> diff --git a/src/front/src/app/upsertproject/upsertproject.controller.js b/src/front/src/app/upsertproject/upsertproject.controller.js index fa1139b..7b18fad 100644 --- a/src/front/src/app/upsertproject/upsertproject.controller.js +++ b/src/front/src/app/upsertproject/upsertproject.controller.js @@ -8,20 +8,20 @@ angular.module('topcoderX').controller('ProjectController', ['currentUser', '$scope', '$timeout', 'ProjectService', '$rootScope', '$state', 'Alert', function (currentUser, $scope, $timeout, ProjectService, $rootScope, $state, Alert) { - //Maintain the navigation state. + // Maintain the navigation state. $timeout(function () { angular.element('#projectsManagement').addClass('active'); }, 0); - //below logic is trying to identify whether we are editing a project + // below logic is trying to identify whether we are editing a project $scope.editing = true; $scope.project = { - 'title': '', - 'tcDirectId': '', - 'repoUrl': '', - 'rocketChatWebhook': null, - 'rocketChatChannelName': null, - 'archived': false + title: '', + tcDirectId: '', + repoUrl: '', + rocketChatWebhook: null, + rocketChatChannelName: null, + archived: false, }; if ($rootScope.project) { $scope.title = 'Edit a Project'; @@ -33,97 +33,40 @@ angular.module('topcoderX').controller('ProjectController', ['currentUser', '$sc $scope.editing = false; } - //represents the repo owner - $scope.repoOwner = ''; - - //represents the repo name - $scope.repoName = ''; - - //represents the repo is located at github or gitlab - $scope.repoType = ''; - - //function to get the repo's owner and the repo's name based on repoUrl - const getRepoDetail = function (repoUrl, callback, errorCallBack) { - $scope.$broadcast('alert.ClearAll', {}); - if (repoUrl.endsWith('/')) { - repoUrl = repoUrl.slice(0, -1); - } - const results = repoUrl.split('/'); - $scope.repoName = results[results.length - 1]; - $scope.repoOwner = results[results.length - 2]; - $scope.repoType = results[results.length - 3].split('.')[0]; - ProjectService.getUserToken($scope.repoOwner, $scope.repoType).then(function (response) { - if (angular.isDefined(response.data.token)) { - $scope.token = response.data.token; - return callback(); - } else { - const erroMessage = 'Token not found for the user ' + $scope.repoOwner + ' of type ' + $scope.repoType + ' please complete profile setting'; - Alert.error(erroMessage, $scope); - } - }, function (error) { - errorCallBack(error); - }); - }; - - //function to add labels to the current project. + // function to add labels to the current project. $scope.addLabels = function () { - getRepoDetail($scope.project.repoUrl, function () { - // for (var i = 0; i < $rootScope.config.LABELS.length; i++) { - var objc = { - 'repoOwner': $scope.repoOwner, - 'repoName': $scope.repoName, - 'repoToken': $scope.token, - - 'repoType': $scope.repoType - }; - ProjectService.createLabel(objc).then(function () { - Alert.info('Label Added Successfully', $scope); - }).catch(function (error) { - Alert.error(error.data.message, $scope); - }); - // } - }, function (error) { + ProjectService.createLabel({ projectId: $scope.project.id }).then(function () { + Alert.info('Label Added Successfully', $scope); + }).catch(function (error) { Alert.error(error.data.message, $scope); }); }; - //function to add hooks to the current project. + // function to add hooks to the current project. $scope.addHooks = function () { - getRepoDetail($scope.project.repoUrl, function () { - var objc = { - 'repoOwner': $scope.repoOwner, - 'repoName': $scope.repoName, - 'repoToken': $scope.token, - 'repoType': $scope.repoType, - 'projectId': $scope.project.id - }; - ProjectService.createHooks(objc).then(function () { - Alert.info('Webhook Added Successfully', $scope); - }).catch(function (error) { - Alert.error(error.data.message, $scope); - }); - }, function (error) { + ProjectService.createHooks({ projectId: $scope.project.id }).then(function () { + Alert.info('Webhook Added Successfully', $scope); + }).catch(function (error) { Alert.error(error.data.message, $scope); }); }; - //save the project info to database, and go back to project list view. + // save the project info to database, and go back to project list view. $scope.save = function () { - $scope.project.username = $rootScope.currentUser.handle; if ($scope.editing) { ProjectService.update($scope.project).then(function () { Alert.info('Project Updated Successfully', $scope); $state.go('app.projects'); - }).catch((function (error) { + }).catch(function (error) { Alert.error(error.data.message, $scope); - })) + }); } else { ProjectService.create($scope.project).then(function () { Alert.info('Project Created Successfully', $scope); $state.go('app.projects'); }).catch(function (error) { Alert.error(error.data.message, $scope); - }) + }); } - } + }; }]); diff --git a/src/services/ProjectService.js b/src/services/ProjectService.js index a88ead0..a400ea0 100644 --- a/src/services/ProjectService.js +++ b/src/services/ProjectService.js @@ -15,9 +15,10 @@ const _ = require('lodash'); const guid = require('guid'); const kafka = require('../utils/kafka'); const helper = require('../common/helper'); -const Project = require('../models').Project; +const models = require('../models'); const config = require('../config'); +const Project = models.Project; const projectSchema = { project: { id: Joi.string().required(), @@ -29,7 +30,8 @@ const projectSchema = { archived: Joi.boolean().required(), username: Joi.string().required(), secretWebhookKey: Joi.string().required(), - } + }, + currentUserTopcoderHandle: Joi.string().required(), }; const createProjectSchema = { @@ -40,16 +42,18 @@ const createProjectSchema = { rocketChatWebhook: Joi.string().allow(null), rocketChatChannelName: Joi.string().allow(null), archived: Joi.boolean().required(), - username: Joi.string().required(), - } + }, + currentUserTopcoderHandle: Joi.string().required(), }; /** * creates project * @param {Object} project the project detail + * @param {String} currentUserTopcoderHandle the topcoder handle of current user * @returns {Object} created project */ -async function create(project) { +async function create(project, currentUserTopcoderHandle) { + await helper.getProviderType(project.repoUrl); /** * Uncomment below code to enable the function of raising event when 'project was created' * @@ -58,7 +62,7 @@ async function create(project) { * } * await kafka.send(JSON.stringify(JSON.stringify(projectCreateEvent))); */ - project.username = project.username.toLowerCase(); + project.username = currentUserTopcoderHandle; project.secretWebhookKey = guid.raw(); const dbProject = new Project(project); return await dbProject.save(); @@ -69,9 +73,11 @@ create.schema = createProjectSchema; /** * updates project * @param {Object} project the project detail + * @param {String} currentUserTopcoderHandle the topcoder handle of current user * @returns {Object} updated project */ -async function update(project) { +async function update(project, currentUserTopcoderHandle) { + await helper.getProviderType(project.repoUrl); const dbProject = await helper.ensureExists(Project, project.id); if (dbProject.archived === 'false' && project.archived === true) { // project archived detected. @@ -90,7 +96,7 @@ async function update(project) { * } * await kafka.send(JSON.stringify(JSON.stringify(projectUpdateEvent))); */ - project.username = project.username.toLowerCase(); + project.username = currentUserTopcoderHandle; Object.entries(project).map((item) => { dbProject[item[0]] = item[1]; return item; @@ -103,29 +109,44 @@ update.schema = projectSchema; /** * gets all projects * @param {String} status the status of project + * @param {String} currentUserTopcoderHandle the topcoder handle of current user * @returns {Array} all projects */ -async function getAll(status) { +async function getAll(status, currentUserTopcoderHandle) { if (status === 'archived') { - return await Project.find({ archived: true }); + return await Project.find({ archived: true, username: currentUserTopcoderHandle }); } - return await Project.find({ archived: false }); + return await Project.find({ archived: false, username: currentUserTopcoderHandle }); } getAll.schema = Joi.object().keys({ status: Joi.string().required().allow('active', 'archived').default('active'), + currentUserTopcoderHandle: Joi.string().required(), }); /** * creates label * @param {Object} body the request body + * @param {String} currentUserTopcoderHandle the topcoder handle of current user * @returns {Object} result */ -async function createLabel(body) { - if (body.repoType === 'github') { +async function createLabel(body, currentUserTopcoderHandle) { + const dbProject = await helper.ensureExists(Project, body.projectId); + if (dbProject.username !== currentUserTopcoderHandle) { + dbProject.username = currentUserTopcoderHandle; + await dbProject.save(); + } + const provider = await helper.getProviderType(dbProject.repoUrl); + const copilot = await helper.getProjectOwner(models, dbProject, provider); + const results = dbProject.repoUrl.split('/'); + let index = 1; + const repoName = results[results.length - index]; + index += 1; + const repoOwner = results[results.length - index]; + if (provider === 'github') { try { - const client = gitHubApi.client(body.repoToken); - const ghrepo = client.repo(`${body.repoOwner}/${body.repoName}`); + const client = gitHubApi.client(copilot.accessToken); + const ghrepo = client.repo(`${repoOwner}/${repoName}`); await Promise.all(config.LABELS.map(async (label) => { await new Promise((resolve, reject) => { ghrepo.label({ @@ -149,10 +170,10 @@ async function createLabel(body) { try { const client = new Gitlab({ url: config.GITLAB_API_BASE_URL, - oauthToken: body.repoToken, + oauthToken: copilot.accessToken, }); await Promise.all(config.LABELS.map(async (label) => { - await client.Labels.create(`${body.repoOwner}/${body.repoName}`, { + await client.Labels.create(`${repoOwner}/${repoName}`, { name: label.name, color: `#${label.color}`, }); @@ -168,24 +189,34 @@ async function createLabel(body) { createLabel.schema = Joi.object().keys({ body: Joi.object().keys({ - repoType: Joi.string().required(), - repoToken: Joi.string().required(), - repoOwner: Joi.string().required(), - repoName: Joi.string().required(), + projectId: Joi.string().required(), }), + currentUserTopcoderHandle: Joi.string().required(), }); /** * creates hook * @param {Object} body the request body + * @param {String} currentUserTopcoderHandle the topcoder handle of current user * @returns {Object} result */ -async function createHook(body) { - const projectDetail = await helper.ensureExists(Project, body.projectId); - if (body.repoType === 'github') { +async function createHook(body, currentUserTopcoderHandle) { + const dbProject = await helper.ensureExists(Project, body.projectId); + if (dbProject.username !== currentUserTopcoderHandle) { + dbProject.username = currentUserTopcoderHandle; + await dbProject.save(); + } + const provider = await helper.getProviderType(dbProject.repoUrl); + const copilot = await helper.getProjectOwner(models, dbProject, provider); + const results = dbProject.repoUrl.split('/'); + let index = 1; + const repoName = results[results.length - index]; + index += 1; + const repoOwner = results[results.length - index]; + if (provider === 'github') { try { - const client = gitHubApi.client(body.repoToken); - const ghrepo = client.repo(`${body.repoOwner}/${body.repoName}`); + const client = gitHubApi.client(copilot.accessToken); + const ghrepo = client.repo(`${repoOwner}/${repoName}`); await new Promise((resolve, reject) => { ghrepo.hook({ name: 'web', @@ -202,7 +233,7 @@ async function createHook(body) { config: { url: `${config.HOOK_BASE_URL}/webhooks/github`, content_type: 'json', - secret: projectDetail.secretWebhookKey, + secret: dbProject.secretWebhookKey, }, }, (error) => { if (error) { @@ -221,9 +252,9 @@ async function createHook(body) { try { const client = new Gitlab({ url: config.GITLAB_API_BASE_URL, - oauthToken: body.repoToken, + oauthToken: copilot.accessToken, }); - await client.ProjectHooks.add(`${body.repoOwner}/${body.repoName}`, + await client.ProjectHooks.add(`${repoOwner}/${repoName}`, `${config.HOOK_BASE_URL}/webhooks/gitlab`, { push_events: true, issues_events: true, @@ -234,7 +265,7 @@ async function createHook(body) { job_events: true, pipeline_events: true, wiki_page_events: true, - token: projectDetail.secretWebhookKey, + token: dbProject.secretWebhookKey, } ); } catch (err) { @@ -244,15 +275,7 @@ async function createHook(body) { return { success: true } } -createHook.schema = Joi.object().keys({ - body: Joi.object().keys({ - projectId: Joi.string().required(), - repoType: Joi.string().required(), - repoOwner: Joi.string().required(), - repoToken: Joi.string().required(), - repoName: Joi.string().required(), - }), -}); +createHook.schema = createLabel.schema; module.exports = { create,