From 7ed9b04c3c4e657356f4031e0328f2a988442201 Mon Sep 17 00:00:00 2001 From: Lucie Germain <116178070+Luvacie84@users.noreply.github.com> Date: Wed, 21 Dec 2022 16:39:13 +0100 Subject: [PATCH] Merge pull request #10983 from overleaf/revert-10901-lg-openapi-chat Revert "Migrate chat service to OpenAPI" GitOrigin-RevId: 39bdfd98bc55f8d9d56fb18bb288749aa13f25e0 --- package-lock.json | 288 +--------------- services/chat/app.js | 5 +- .../Messages/MessageHttpController.js | 164 +++------ services/chat/app/js/router.js | 65 ++++ services/chat/app/js/server.js | 45 +-- services/chat/chat.yaml | 317 ------------------ services/chat/package.json | 10 +- .../acceptance/js/GettingMessagesTests.js | 3 - .../acceptance/js/SendingAMessageTests.js | 4 +- .../test/acceptance/js/helpers/ChatApp.js | 15 +- .../test/acceptance/js/helpers/ChatClient.js | 36 +- 11 files changed, 150 insertions(+), 802 deletions(-) create mode 100644 services/chat/app/js/router.js delete mode 100644 services/chat/chat.yaml diff --git a/package-lock.json b/package-lock.json index 4bed2eccb4..e86fd09de6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1022,17 +1022,6 @@ "name": "@overleaf/settings", "version": "3.0.0" }, - "node_modules/@apidevtools/json-schema-ref-parser": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz", - "integrity": "sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==", - "dependencies": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.6", - "call-me-maybe": "^1.0.1", - "js-yaml": "^4.1.0" - } - }, "node_modules/@arrows/array": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@arrows/array/-/array-1.4.1.tgz", @@ -5160,11 +5149,6 @@ "node": ">=8" } }, - "node_modules/@jsdevtools/ono": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" - }, "node_modules/@juggle/resize-observer": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.3.1.tgz", @@ -10399,6 +10383,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "devOptional": true, "dependencies": { "ajv": "^8.0.0" }, @@ -10415,6 +10400,7 @@ "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "devOptional": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -10429,7 +10415,8 @@ "node_modules/ajv-formats/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "devOptional": true }, "node_modules/ajv-keywords": { "version": "3.5.2", @@ -12429,11 +12416,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==" - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -14765,11 +14747,6 @@ "node": ">=4.0.0" } }, - "node_modules/deep-freeze": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz", - "integrity": "sha512-Z+z8HiAvsGwmjqlphnHW5oz6yWlOwu6EQfFTjmeTWlDeda3FS2yv3jhq35TX/ewmsnqB+RX2IdsIOyjJCQN5tg==" - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -16848,11 +16825,6 @@ "node": ">=0.4.x" } }, - "node_modules/events-listener": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/events-listener/-/events-listener-1.1.0.tgz", - "integrity": "sha512-Kd3EgYfODHueq6GzVfs/VUolh2EgJsS8hkO3KpnDrxVjU3eq63eXM2ujXkhPP+OkeUOhL8CxdfZbQXzryb5C4g==" - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -16909,96 +16881,6 @@ "node": ">=4" } }, - "node_modules/exegesis": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/exegesis/-/exegesis-4.1.1.tgz", - "integrity": "sha512-PvSqaMOw2absLBgsthtJyVOeCHN4lxQ1dM7ibXb6TfZZJaoXtGELoEAGJRFvdN16+u9kg8oy1okZXRk8VpimWA==", - "dependencies": { - "@apidevtools/json-schema-ref-parser": "^9.0.3", - "ajv": "^8.3.0", - "ajv-formats": "^2.1.0", - "body-parser": "^1.18.3", - "content-type": "^1.0.4", - "deep-freeze": "0.0.1", - "events-listener": "^1.1.0", - "glob": "^7.1.3", - "json-ptr": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "lodash": "^4.17.11", - "openapi3-ts": "^3.1.1", - "promise-breaker": "^6.0.0", - "pump": "^3.0.0", - "qs": "^6.6.0", - "raw-body": "^2.3.3", - "semver": "^7.0.0" - }, - "engines": { - "node": ">=6.0.0", - "npm": ">5.0.0" - } - }, - "node_modules/exegesis-express": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/exegesis-express/-/exegesis-express-4.0.0.tgz", - "integrity": "sha512-V2hqwTtYRj0bj43K4MCtm0caD97YWkqOUHFMRCBW5L1x9IjyqOEc7Xa4oQjjiFbeFOSQzzwPV+BzXsQjSz08fw==", - "dependencies": { - "exegesis": "^4.1.0" - }, - "engines": { - "node": ">=6.0.0", - "npm": ">5.0.0" - } - }, - "node_modules/exegesis/node_modules/ajv": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz", - "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/exegesis/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/exegesis/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/exegesis/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/exegesis/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/exifr": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/exifr/-/exifr-6.3.0.tgz", @@ -22538,11 +22420,6 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "node_modules/json-ptr": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/json-ptr/-/json-ptr-3.1.1.tgz", - "integrity": "sha512-SiSJQ805W1sDUCD1+/t1/1BIrveq2Fe9HJqENxZmMCILmrPI7WhS/pePpIOx85v6/H2z1Vy7AI08GV2TzfXocg==" - }, "node_modules/json-refs": { "version": "3.0.15", "resolved": "https://registry.npmjs.org/json-refs/-/json-refs-3.0.15.tgz", @@ -26919,22 +26796,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/openapi3-ts": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/openapi3-ts/-/openapi3-ts-3.1.2.tgz", - "integrity": "sha512-S8fijNOqe/ut0kEDAwHZnI7sVYqb8Q3XnISmSyXmK76jgrcf4ableI75KTY1qdksd9EI/t39Vi5M4VYKrkNKfQ==", - "dependencies": { - "yaml": "^2.1.3" - } - }, - "node_modules/openapi3-ts/node_modules/yaml": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz", - "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==", - "engines": { - "node": ">= 14" - } - }, "node_modules/openid-client": { "version": "3.15.10", "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-3.15.10.tgz", @@ -28474,11 +28335,6 @@ "asap": "~2.0.3" } }, - "node_modules/promise-breaker": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/promise-breaker/-/promise-breaker-6.0.0.tgz", - "integrity": "sha512-BthzO9yTPswGf7etOBiHCVuugs2N01/Q/94dIPls48z2zCmrnDptUUZzfIb+41xq0MnYZ/BzmOd6ikDR4ibNZA==" - }, "node_modules/promise.prototype.finally": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/promise.prototype.finally/-/promise.prototype.finally-3.1.3.tgz", @@ -35915,15 +35771,12 @@ }, "services/chat": { "name": "@overleaf/chat", - "version": "1.0.0", - "license": "ISC", "dependencies": { "@overleaf/logger": "*", "@overleaf/metrics": "*", "@overleaf/settings": "*", "async": "^3.2.2", "body-parser": "^1.19.0", - "exegesis-express": "^4.0.0", "express": "4.17.1", "mongodb": "^4.11.0" }, @@ -41744,17 +41597,6 @@ } }, "dependencies": { - "@apidevtools/json-schema-ref-parser": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz", - "integrity": "sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==", - "requires": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.6", - "call-me-maybe": "^1.0.1", - "js-yaml": "^4.1.0" - } - }, "@arrows/array": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@arrows/array/-/array-1.4.1.tgz", @@ -44959,11 +44801,6 @@ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, - "@jsdevtools/ono": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" - }, "@juggle/resize-observer": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.3.1.tgz", @@ -46919,7 +46756,6 @@ "body-parser": "^1.19.0", "chai": "^4.3.6", "chai-as-promised": "^7.1.1", - "exegesis-express": "^4.0.0", "express": "4.17.1", "mocha": "^8.4.0", "mongodb": "^4.11.0", @@ -53662,6 +53498,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "devOptional": true, "requires": { "ajv": "^8.0.0" }, @@ -53670,6 +53507,7 @@ "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "devOptional": true, "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -53680,7 +53518,8 @@ "json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "devOptional": true } } }, @@ -55252,11 +55091,6 @@ "get-intrinsic": "^1.0.2" } }, - "call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==" - }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -57095,11 +56929,6 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, - "deep-freeze": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz", - "integrity": "sha512-Z+z8HiAvsGwmjqlphnHW5oz6yWlOwu6EQfFTjmeTWlDeda3FS2yv3jhq35TX/ewmsnqB+RX2IdsIOyjJCQN5tg==" - }, "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -58693,11 +58522,6 @@ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" }, - "events-listener": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/events-listener/-/events-listener-1.1.0.tgz", - "integrity": "sha512-Kd3EgYfODHueq6GzVfs/VUolh2EgJsS8hkO3KpnDrxVjU3eq63eXM2ujXkhPP+OkeUOhL8CxdfZbQXzryb5C4g==" - }, "execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -58738,77 +58562,6 @@ "pify": "^2.2.0" } }, - "exegesis": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/exegesis/-/exegesis-4.1.1.tgz", - "integrity": "sha512-PvSqaMOw2absLBgsthtJyVOeCHN4lxQ1dM7ibXb6TfZZJaoXtGELoEAGJRFvdN16+u9kg8oy1okZXRk8VpimWA==", - "requires": { - "@apidevtools/json-schema-ref-parser": "^9.0.3", - "ajv": "^8.3.0", - "ajv-formats": "^2.1.0", - "body-parser": "^1.18.3", - "content-type": "^1.0.4", - "deep-freeze": "0.0.1", - "events-listener": "^1.1.0", - "glob": "^7.1.3", - "json-ptr": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "lodash": "^4.17.11", - "openapi3-ts": "^3.1.1", - "promise-breaker": "^6.0.0", - "pump": "^3.0.0", - "qs": "^6.6.0", - "raw-body": "^2.3.3", - "semver": "^7.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz", - "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==", - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "exegesis-express": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/exegesis-express/-/exegesis-express-4.0.0.tgz", - "integrity": "sha512-V2hqwTtYRj0bj43K4MCtm0caD97YWkqOUHFMRCBW5L1x9IjyqOEc7Xa4oQjjiFbeFOSQzzwPV+BzXsQjSz08fw==", - "requires": { - "exegesis": "^4.1.0" - } - }, "exifr": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/exifr/-/exifr-6.3.0.tgz", @@ -63172,11 +62925,6 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "json-ptr": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/json-ptr/-/json-ptr-3.1.1.tgz", - "integrity": "sha512-SiSJQ805W1sDUCD1+/t1/1BIrveq2Fe9HJqENxZmMCILmrPI7WhS/pePpIOx85v6/H2z1Vy7AI08GV2TzfXocg==" - }, "json-refs": { "version": "3.0.15", "resolved": "https://registry.npmjs.org/json-refs/-/json-refs-3.0.15.tgz", @@ -66702,21 +66450,6 @@ "is-wsl": "^2.2.0" } }, - "openapi3-ts": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/openapi3-ts/-/openapi3-ts-3.1.2.tgz", - "integrity": "sha512-S8fijNOqe/ut0kEDAwHZnI7sVYqb8Q3XnISmSyXmK76jgrcf4ableI75KTY1qdksd9EI/t39Vi5M4VYKrkNKfQ==", - "requires": { - "yaml": "^2.1.3" - }, - "dependencies": { - "yaml": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz", - "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==" - } - } - }, "openid-client": { "version": "3.15.10", "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-3.15.10.tgz", @@ -68372,11 +68105,6 @@ "asap": "~2.0.3" } }, - "promise-breaker": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/promise-breaker/-/promise-breaker-6.0.0.tgz", - "integrity": "sha512-BthzO9yTPswGf7etOBiHCVuugs2N01/Q/94dIPls48z2zCmrnDptUUZzfIb+41xq0MnYZ/BzmOd6ikDR4ibNZA==" - }, "promise.prototype.finally": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/promise.prototype.finally/-/promise.prototype.finally-3.1.3.tgz", diff --git a/services/chat/app.js b/services/chat/app.js index d47bd2594c..ca3ea09426 100644 --- a/services/chat/app.js +++ b/services/chat/app.js @@ -1,14 +1,13 @@ import logger from '@overleaf/logger' import settings from '@overleaf/settings' import { mongoClient } from './app/js/mongodb.js' -import { createServer } from './app/js/server.js' +import { server } from './app/js/server.js' const port = settings.internal.chat.port const host = settings.internal.chat.host mongoClient .connect() - .then(async () => { - const { server } = await createServer() + .then(() => { server.listen(port, host, function (err) { if (err) { logger.fatal({ err }, `Cannot bind to ${host}:${port}. Exiting.`) diff --git a/services/chat/app/js/Features/Messages/MessageHttpController.js b/services/chat/app/js/Features/Messages/MessageHttpController.js index 0d65a4a360..7ccf63bb97 100644 --- a/services/chat/app/js/Features/Messages/MessageHttpController.js +++ b/services/chat/app/js/Features/Messages/MessageHttpController.js @@ -3,105 +3,24 @@ import * as MessageManager from './MessageManager.js' import * as MessageFormatter from './MessageFormatter.js' import * as ThreadManager from '../Threads/ThreadManager.js' import { ObjectId } from '../../mongodb.js' +import { expressify } from '../../util/promises.js' const DEFAULT_MESSAGE_LIMIT = 50 const MAX_MESSAGE_LENGTH = 10 * 1024 // 10kb, about 1,500 words -async function readContext(context, req) { - req.body = context.requestBody - req.params = context.params.path - req.query = context.params.query - if (typeof req.params.projectId !== 'undefined') { - if (!ObjectId.isValid(req.params.projectId)) { - context.res.status(400).setBody('Invalid projectId') - } - } - if (typeof req.params.threadId !== 'undefined') { - if (!ObjectId.isValid(req.params.threadId)) { - context.res.status(400).setBody('Invalid threadId') - } - } -} - -export async function callMessageHttpController(context, ControllerMethod) { - const req = {} - readContext(context, req) - if (context.res.statusCode !== 400) { - return await ControllerMethod(req, context.res) - } else { - return context.res.body - } -} - -export async function getGlobalMessages(context) { - return await callMessageHttpController(context, _getGlobalMessages) -} - -export async function sendGlobalMessage(context) { - return await callMessageHttpController(context, _sendGlobalMessage) -} - -export async function sendMessage(context) { - return await callMessageHttpController(context, _sendThreadMessage) -} - -export async function getThreads(context) { - return await callMessageHttpController(context, _getAllThreads) -} - -export async function resolveThread(context) { - return await callMessageHttpController(context, _resolveThread) -} - -export async function reopenThread(context) { - return await callMessageHttpController(context, _reopenThread) -} - -export async function deleteThread(context) { - return await callMessageHttpController(context, _deleteThread) -} - -export async function editMessage(context) { - return await callMessageHttpController(context, _editMessage) -} - -export async function deleteMessage(context) { - return await callMessageHttpController(context, _deleteMessage) -} - -export async function destroyProject(context) { - return await callMessageHttpController(context, _destroyProject) -} - -export async function getStatus(context) { - const message = 'chat is alive' - context.res.status(200).setBody(message) - return message -} - -const _getGlobalMessages = async (req, res) => { +export const getGlobalMessages = expressify(async (req, res) => { await _getMessages(ThreadManager.GLOBAL_THREAD, req, res) -} +}) -async function _sendGlobalMessage(req, res) { - const { user_id: userId, content } = req.body - const { projectId } = req.params - return await _sendMessage( - userId, - projectId, - content, - ThreadManager.GLOBAL_THREAD, - res - ) -} +export const sendGlobalMessage = expressify(async (req, res) => { + await _sendMessage(ThreadManager.GLOBAL_THREAD, req, res) +}) -async function _sendThreadMessage(req, res) { - const { user_id: userId, content } = req.body - const { projectId, threadId } = req.params - return await _sendMessage(userId, projectId, content, threadId, res) -} +export const sendThreadMessage = expressify(async (req, res) => { + await _sendMessage(req.params.threadId, req, res) +}) -const _getAllThreads = async (req, res) => { +export const getAllThreads = expressify(async (req, res) => { const { projectId } = req.params logger.debug({ projectId }, 'getting all threads') const rooms = await ThreadManager.findAllThreadRooms(projectId) @@ -109,32 +28,32 @@ const _getAllThreads = async (req, res) => { const messages = await MessageManager.findAllMessagesInRooms(roomIds) const threads = MessageFormatter.groupMessagesByThreads(rooms, messages) res.json(threads) -} +}) -const _resolveThread = async (req, res) => { +export const resolveThread = expressify(async (req, res) => { const { projectId, threadId } = req.params const { user_id: userId } = req.body logger.debug({ userId, projectId, threadId }, 'marking thread as resolved') await ThreadManager.resolveThread(projectId, threadId, userId) - res.status(204) -} + res.sendStatus(204) +}) -const _reopenThread = async (req, res) => { +export const reopenThread = expressify(async (req, res) => { const { projectId, threadId } = req.params logger.debug({ projectId, threadId }, 'reopening thread') await ThreadManager.reopenThread(projectId, threadId) - res.status(204) -} + res.sendStatus(204) +}) -const _deleteThread = async (req, res) => { +export const deleteThread = expressify(async (req, res) => { const { projectId, threadId } = req.params logger.debug({ projectId, threadId }, 'deleting thread') const roomId = await ThreadManager.deleteThread(projectId, threadId) await MessageManager.deleteAllMessagesInRoom(roomId) - res.status(204) -} + res.sendStatus(204) +}) -const _editMessage = async (req, res) => { +export const editMessage = expressify(async (req, res) => { const { content, userId } = req.body const { projectId, threadId, messageId } = req.params logger.debug({ projectId, threadId, messageId, content }, 'editing message') @@ -147,21 +66,20 @@ const _editMessage = async (req, res) => { Date.now() ) if (!found) { - res.status(404) - return + return res.sendStatus(404) } - res.status(204) -} + res.sendStatus(204) +}) -const _deleteMessage = async (req, res) => { +export const deleteMessage = expressify(async (req, res) => { const { projectId, threadId, messageId } = req.params logger.debug({ projectId, threadId, messageId }, 'deleting message') const room = await ThreadManager.findOrCreateThread(projectId, threadId) await MessageManager.deleteMessage(room._id, messageId) - res.status(204) -} + res.sendStatus(204) +}) -const _destroyProject = async (req, res) => { +export const destroyProject = expressify(async (req, res) => { const { projectId } = req.params logger.debug({ projectId }, 'destroying project') const rooms = await ThreadManager.findAllThreadRoomsAndGlobalThread(projectId) @@ -170,24 +88,22 @@ const _destroyProject = async (req, res) => { await MessageManager.deleteAllMessagesInRooms(roomIds) logger.debug({ projectId }, 'deleting all threads in project') await ThreadManager.deleteAllThreadsInProject(projectId) - res.status(204) -} + res.sendStatus(204) +}) -async function _sendMessage(userId, projectId, content, clientThreadId, res) { +async function _sendMessage(clientThreadId, req, res) { + const { user_id: userId, content } = req.body + const { projectId } = req.params if (!ObjectId.isValid(userId)) { - const message = 'Invalid userId' - res.status(400).setBody(message) - return message + return res.status(400).send('Invalid userId') } if (!content) { - const message = 'No content provided' - res.status(400).setBody(message) - return message + return res.status(400).send('No content provided') } if (content.length > MAX_MESSAGE_LENGTH) { - const message = `Content too long (> ${MAX_MESSAGE_LENGTH} bytes)` - res.status(400).setBody(message) - return message + return res + .status(400) + .send(`Content too long (> ${MAX_MESSAGE_LENGTH} bytes)`) } logger.debug( { clientThreadId, projectId, userId, content }, @@ -205,7 +121,7 @@ async function _sendMessage(userId, projectId, content, clientThreadId, res) { ) message = MessageFormatter.formatMessageForClientSide(message) message.room_id = projectId - res.status(201).setBody(message) + res.status(201).send(message) } async function _getMessages(clientThreadId, req, res) { @@ -237,5 +153,5 @@ async function _getMessages(clientThreadId, req, res) { let messages = await MessageManager.getMessages(threadObjectId, limit, before) messages = MessageFormatter.formatMessagesForClientSide(messages) logger.debug({ projectId, messages }, 'got messages') - res.status(200).setBody(messages) + res.status(200).send(messages) } diff --git a/services/chat/app/js/router.js b/services/chat/app/js/router.js new file mode 100644 index 0000000000..d7d7a135b6 --- /dev/null +++ b/services/chat/app/js/router.js @@ -0,0 +1,65 @@ +import * as MessageHttpController from './Features/Messages/MessageHttpController.js' +import { ObjectId } from './mongodb.js' + +export function route(app) { + app.param('projectId', function (req, res, next, projectId) { + if (ObjectId.isValid(projectId)) { + next() + } else { + res.status(400).send('Invalid projectId') + } + }) + + app.param('threadId', function (req, res, next, threadId) { + if (ObjectId.isValid(threadId)) { + next() + } else { + res.status(400).send('Invalid threadId') + } + }) + + // These are for backwards compatibility + app.get('/room/:projectId/messages', MessageHttpController.getGlobalMessages) + app.post('/room/:projectId/messages', MessageHttpController.sendGlobalMessage) + + app.get( + '/project/:projectId/messages', + MessageHttpController.getGlobalMessages + ) + app.post( + '/project/:projectId/messages', + MessageHttpController.sendGlobalMessage + ) + + app.post( + '/project/:projectId/thread/:threadId/messages', + MessageHttpController.sendThreadMessage + ) + app.get('/project/:projectId/threads', MessageHttpController.getAllThreads) + + app.post( + '/project/:projectId/thread/:threadId/messages/:messageId/edit', + MessageHttpController.editMessage + ) + app.delete( + '/project/:projectId/thread/:threadId/messages/:messageId', + MessageHttpController.deleteMessage + ) + + app.post( + '/project/:projectId/thread/:threadId/resolve', + MessageHttpController.resolveThread + ) + app.post( + '/project/:projectId/thread/:threadId/reopen', + MessageHttpController.reopenThread + ) + app.delete( + '/project/:projectId/thread/:threadId', + MessageHttpController.deleteThread + ) + + app.delete('/project/:projectId', MessageHttpController.destroyProject) + + app.get('/status', (req, res, next) => res.send('chat is alive')) +} diff --git a/services/chat/app/js/server.js b/services/chat/app/js/server.js index b75a84b912..21ebe2be58 100644 --- a/services/chat/app/js/server.js +++ b/services/chat/app/js/server.js @@ -2,45 +2,18 @@ import http from 'http' import metrics from '@overleaf/metrics' import logger from '@overleaf/logger' import express from 'express' -import exegesisExpress from 'exegesis-express' -import path from 'path' -import { fileURLToPath } from 'url' -import * as messagesController from './Features/Messages/MessageHttpController.js' - -const __dirname = fileURLToPath(new URL('.', import.meta.url)) +import bodyParser from 'body-parser' +import * as Router from './router.js' metrics.initialize('chat') logger.initialize('chat') -export async function createServer() { - const app = express() +export const app = express() +export const server = http.createServer(app) - // See https://github.com/exegesis-js/exegesis/blob/master/docs/Options.md - const options = { - controllers: { messagesController }, - ignoreServers: true, - allowMissingControllers: false, - } +app.use(bodyParser.json()) +app.use(bodyParser.urlencoded({ extended: true })) +app.use(metrics.http.monitor(logger)) +metrics.injectMetricsRoute(app) - // const exegesisMiddleware = await exegesisExpress.middleware( - const exegesisMiddleware = await exegesisExpress.middleware( - path.resolve(__dirname, '../../chat.yaml'), - options - ) - - // If you have any body parsers, this should go before them. - app.use(exegesisMiddleware) - - // Return a 404 - app.use((req, res) => { - res.status(404).json({ message: `Not found` }) - }) - - // Handle any unexpected errors - app.use((err, req, res, next) => { - res.status(500).json({ message: `Internal error: ${err.message}` }) - }) - - const server = http.createServer(app) - return { app, server } -} +Router.route(app) diff --git a/services/chat/chat.yaml b/services/chat/chat.yaml deleted file mode 100644 index a2568b0afc..0000000000 --- a/services/chat/chat.yaml +++ /dev/null @@ -1,317 +0,0 @@ -openapi: 3.1.0 -x-stoplight: - id: okoe8mh50pjec -info: - title: chat - version: '1.0' -servers: - - url: 'http://chat:3010' -x-exegesis-controller: messagesController -paths: - '/project/{projectId}/messages': - parameters: - - schema: - type: string - name: projectId - in: path - required: true - get: - summary: Get Global messages - tags: [] - responses: - '201': - description: OK - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/Message' - operationId: getGlobalMessages - description: Get global messages for the project with Project ID provided - parameters: - - schema: - type: string - in: query - name: before - - schema: - type: string - in: query - name: limit - post: - summary: Send Global message - operationId: sendGlobalMessage - responses: - '201': - description: OK - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Message' - examples: - example-1: - value: - user_id: string - content: string - description: 'UserID and Content of the message to be posted. ' - description: Send global message for the project with Project ID provided - '/project/{projectId}/thread/{threadId}/messages': - parameters: - - schema: - type: string - name: projectId - in: path - required: true - - schema: - type: string - name: threadId - in: path - required: true - post: - summary: Send message - operationId: sendMessage - responses: - '201': - description: Created - description: Add a message to the thread with thread ID provided from the Project with Project ID provided. - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Message' - description: |- - JSON object with : - - user_id: Id of the user - - content: Content of the message - '/project/{projectId}/threads': - parameters: - - schema: - type: string - name: projectId - in: path - required: true - get: - summary: Get Threads - tags: [] - responses: - '200': - description: OK - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/Thread' - examples: {} - '404': - description: Not Found - operationId: getThreads - description: Get the list of threads for the project with Project ID provided - '/project/{projectId}/thread/{threadId}/messages/{messageId}/edit': - parameters: - - schema: - type: string - name: projectId - in: path - required: true - - schema: - type: string - name: threadId - in: path - required: true - - schema: - type: string - name: messageId - in: path - required: true - post: - summary: Edit message - operationId: editMessage - responses: - '204': - description: No Content - '404': - description: Not Found - requestBody: - content: - application/json: - schema: - type: object - properties: - content: - type: string - user_id: - type: string - readOnly: true - required: - - content - examples: {} - description: |- - JSON object with : - - content: Content of the message to edit - - user_id: Id of the user (optional) - description: | - Update message with Message ID provided from the Thread ID and Project ID provided - '/project/{projectId}/thread/{threadId}/messages/{messageId}': - parameters: - - schema: - type: string - name: projectId - in: path - required: true - - schema: - type: string - name: threadId - in: path - required: true - - schema: - type: string - name: messageId - in: path - required: true - delete: - summary: Delete message - operationId: deleteMessage - responses: - '204': - description: No Content - description: 'Delete message with Message ID provided, from the Thread with ThreadID and ProjectID provided' - '/project/{projectId}/thread/{threadId}/resolve': - parameters: - - schema: - type: string - name: projectId - in: path - required: true - - schema: - type: string - name: threadId - in: path - required: true - post: - summary: Resolve Thread - operationId: resolveThread - responses: - '204': - description: No Content - requestBody: - content: - application/json: - schema: - type: object - properties: - user_id: - type: string - required: - - user_id - description: |- - JSON object with : - - user_id: Id of the user. - description: Mark Thread with ThreadID and ProjectID provided owned by the user with UserID provided as resolved. - '/project/{projectId}/thread/{threadId}/reopen': - parameters: - - schema: - type: string - name: projectId - in: path - required: true - - schema: - type: string - name: threadId - in: path - required: true - post: - summary: Reopen Thread - operationId: reopenThread - responses: - '204': - description: No Content - description: |- - Reopen Thread with ThreadID and ProjectID provided. - i.e unmark it as resolved. - '/project/{projectId}/thread/{threadId}': - parameters: - - schema: - type: string - name: projectId - in: path - required: true - - schema: - type: string - name: threadId - in: path - required: true - delete: - summary: Delete thread - operationId: deleteThread - responses: - '204': - description: No Content - description: Delete thread with ThreadID and ProjectID provided - '/project/{projectId}': - parameters: - - schema: - type: string - name: projectId - in: path - required: true - delete: - summary: Destroy project - operationId: destroyProject - responses: - '204': - description: No Content - description: 'Delete all threads from Project with Project ID provided, and all messages in those threads.' - /status: - get: - summary: Check status - tags: [] - responses: - '200': - description: OK - content: - application/json: - schema: - type: string - description: chat is alive - operationId: getStatus - description: Check that the Chat service is alive - head: - summary: Check status - tags: [] - responses: - '200': - description: OK - content: - application/json: - schema: - type: string - description: chat is alive - operationId: getStatus - description: Check that the Chat service is alive -components: - schemas: - Message: - title: Message - x-stoplight: - id: ue9n1vvezlutw - type: object - examples: - - user_id: string - - content: string - properties: - user_id: - type: string - content: - type: string - required: - - user_id - - content - Thread: - title: Thread - x-stoplight: - id: 0ppt3jw4h5bua - type: array - items: - $ref: '#/components/schemas/Message' diff --git a/services/chat/package.json b/services/chat/package.json index 5cd892f519..00da2fe1b8 100644 --- a/services/chat/package.json +++ b/services/chat/package.json @@ -22,7 +22,6 @@ "@overleaf/settings": "*", "async": "^3.2.2", "body-parser": "^1.19.0", - "exegesis-express": "^4.0.0", "express": "4.17.1", "mongodb": "^4.11.0" }, @@ -36,12 +35,5 @@ "sandboxed-module": "^2.0.4", "sinon": "^9.2.4", "timekeeper": "^2.2.0" - }, - "version": "1.0.0", - "directories": { - "test": "test" - }, - "keywords": [], - "author": "", - "license": "AGPL-3.0" + } } diff --git a/services/chat/test/acceptance/js/GettingMessagesTests.js b/services/chat/test/acceptance/js/GettingMessagesTests.js index 0e5cb6fd6c..83f0c8c137 100644 --- a/services/chat/test/acceptance/js/GettingMessagesTests.js +++ b/services/chat/test/acceptance/js/GettingMessagesTests.js @@ -28,9 +28,6 @@ describe('Getting messages', async function () { content2 ) expect(response2.statusCode).to.equal(201) - const { response: response3, body } = await ChatClient.checkStatus() - expect(response3.statusCode).to.equal(200) - expect(body).to.equal('chat is alive') }) it('should contain the messages and populated users when getting the messages', async function () { diff --git a/services/chat/test/acceptance/js/SendingAMessageTests.js b/services/chat/test/acceptance/js/SendingAMessageTests.js index ab5e0fe7f0..900ac32e64 100644 --- a/services/chat/test/acceptance/js/SendingAMessageTests.js +++ b/services/chat/test/acceptance/js/SendingAMessageTests.js @@ -122,9 +122,7 @@ describe('Sending a message', async function () { null ) expect(response.statusCode).to.equal(400) - // Exegesis is responding with validation errors. I can“t find a way to choose the validation error yet. - // expect(body).to.equal('No content provided') - expect(body.message).to.equal('Validation errors') + expect(body).to.equal('No content provided') }) }) diff --git a/services/chat/test/acceptance/js/helpers/ChatApp.js b/services/chat/test/acceptance/js/helpers/ChatApp.js index 848268f516..9286842e2e 100644 --- a/services/chat/test/acceptance/js/helpers/ChatApp.js +++ b/services/chat/test/acceptance/js/helpers/ChatApp.js @@ -1,15 +1,20 @@ -import { createServer } from '../../../../app/js/server.js' -import { promisify } from 'util' +import { server } from '../../../../app/js/server.js' export { db } from '../../../../app/js/mongodb.js' let serverPromise = null +function startServer(resolve, reject) { + server.listen(3010, 'localhost', error => { + if (error) { + return reject(error) + } + resolve() + }) +} export async function ensureRunning() { if (!serverPromise) { - const { app } = await createServer() - const startServer = promisify(app.listen.bind(app)) - serverPromise = startServer(3010, 'localhost') + serverPromise = new Promise(startServer) } return serverPromise } diff --git a/services/chat/test/acceptance/js/helpers/ChatClient.js b/services/chat/test/acceptance/js/helpers/ChatClient.js index 433b6fcd71..4827099cd5 100644 --- a/services/chat/test/acceptance/js/helpers/ChatClient.js +++ b/services/chat/test/acceptance/js/helpers/ChatClient.js @@ -64,6 +64,20 @@ export async function resolveThread(projectId, threadId, userId) { }) } +export async function reopenThread(projectId, threadId) { + return asyncRequest({ + method: 'post', + url: `/project/${projectId}/thread/${threadId}/reopen`, + }) +} + +export async function deleteThread(projectId, threadId) { + return asyncRequest({ + method: 'delete', + url: `/project/${projectId}/thread/${threadId}`, + }) +} + export async function editMessage(projectId, threadId, messageId, content) { return asyncRequest({ method: 'post', @@ -91,28 +105,6 @@ export async function editMessageWithUser( }) } -export async function checkStatus() { - return asyncRequest({ - method: 'get', - url: `/status`, - json: true, - }) -} - -export async function reopenThread(projectId, threadId) { - return asyncRequest({ - method: 'post', - url: `/project/${projectId}/thread/${threadId}/reopen`, - }) -} - -export async function deleteThread(projectId, threadId) { - return asyncRequest({ - method: 'delete', - url: `/project/${projectId}/thread/${threadId}`, - }) -} - export async function deleteMessage(projectId, threadId, messageId) { return asyncRequest({ method: 'delete',