mirror of
https://github.com/wassname/talk.git
synced 2026-09-13 13:10:43 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b73a5fcd7 | ||
|
|
1503b735e5 | ||
|
|
6db72db837 | ||
|
|
18b274a6a9 | ||
|
|
78cfb4cac8 |
@@ -69,6 +69,9 @@ jobs:
|
||||
command: |
|
||||
npm run doctoc
|
||||
git diff --exit-code
|
||||
- run:
|
||||
name: Lint Versions
|
||||
command: npx @coralproject/package-version-lint
|
||||
|
||||
# unit_tests will run the unit tests.
|
||||
unit_tests:
|
||||
@@ -141,6 +144,9 @@ jobs:
|
||||
<<: *job_defaults
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Verify release version
|
||||
command: npx @coralproject/package-version-lint --expect ${CIRCLE_TAG/#v}
|
||||
- setup_remote_docker
|
||||
- deploy:
|
||||
name: Deploy the code
|
||||
|
||||
Generated
+255
-42
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@coralproject/talk",
|
||||
"version": "5.5.1",
|
||||
"version": "6.0.3",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -8680,20 +8680,95 @@
|
||||
"dev": true
|
||||
},
|
||||
"body-parser": {
|
||||
"version": "1.18.2",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz",
|
||||
"integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=",
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
|
||||
"integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
|
||||
"requires": {
|
||||
"bytes": "3.0.0",
|
||||
"bytes": "3.1.0",
|
||||
"content-type": "~1.0.4",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.1",
|
||||
"http-errors": "~1.6.2",
|
||||
"iconv-lite": "0.4.19",
|
||||
"depd": "~1.1.2",
|
||||
"http-errors": "1.7.2",
|
||||
"iconv-lite": "0.4.24",
|
||||
"on-finished": "~2.3.0",
|
||||
"qs": "6.5.1",
|
||||
"raw-body": "2.3.2",
|
||||
"type-is": "~1.6.15"
|
||||
"qs": "6.7.0",
|
||||
"raw-body": "2.4.0",
|
||||
"type-is": "~1.6.17"
|
||||
},
|
||||
"dependencies": {
|
||||
"bytes": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
||||
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
|
||||
"integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
|
||||
"requires": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.3",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.0"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.43.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
|
||||
"integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.26",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
|
||||
"integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
|
||||
"requires": {
|
||||
"mime-db": "1.43.0"
|
||||
}
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
|
||||
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
|
||||
},
|
||||
"raw-body": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
|
||||
"integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
|
||||
"requires": {
|
||||
"bytes": "3.1.0",
|
||||
"http-errors": "1.7.2",
|
||||
"iconv-lite": "0.4.24",
|
||||
"unpipe": "1.0.0"
|
||||
}
|
||||
},
|
||||
"setprototypeof": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
|
||||
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
|
||||
},
|
||||
"type-is": {
|
||||
"version": "1.6.18",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
|
||||
"requires": {
|
||||
"media-typer": "0.3.0",
|
||||
"mime-types": "~2.1.24"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"bonjour": {
|
||||
@@ -10373,7 +10448,8 @@
|
||||
"content-disposition": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
|
||||
"integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
|
||||
"integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=",
|
||||
"dev": true
|
||||
},
|
||||
"content-security-policy-builder": {
|
||||
"version": "2.0.0",
|
||||
@@ -15674,46 +15750,182 @@
|
||||
"integrity": "sha512-6SK3MG/Bbhm8MsgyJAylg+ucIOU71/FzyFalcfu5nY19dH8y/z0tBJU0wrNBXD4B27EoQtqPF/9wqH0iYAd04g=="
|
||||
},
|
||||
"express": {
|
||||
"version": "4.16.3",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz",
|
||||
"integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=",
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
|
||||
"integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
|
||||
"requires": {
|
||||
"accepts": "~1.3.5",
|
||||
"accepts": "~1.3.7",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.18.2",
|
||||
"content-disposition": "0.5.2",
|
||||
"body-parser": "1.19.0",
|
||||
"content-disposition": "0.5.3",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.3.1",
|
||||
"cookie": "0.4.0",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"finalhandler": "1.1.1",
|
||||
"finalhandler": "~1.1.2",
|
||||
"fresh": "0.5.2",
|
||||
"merge-descriptors": "1.0.1",
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "~2.3.0",
|
||||
"parseurl": "~1.3.2",
|
||||
"parseurl": "~1.3.3",
|
||||
"path-to-regexp": "0.1.7",
|
||||
"proxy-addr": "~2.0.3",
|
||||
"qs": "6.5.1",
|
||||
"range-parser": "~1.2.0",
|
||||
"safe-buffer": "5.1.1",
|
||||
"send": "0.16.2",
|
||||
"serve-static": "1.13.2",
|
||||
"setprototypeof": "1.1.0",
|
||||
"statuses": "~1.4.0",
|
||||
"type-is": "~1.6.16",
|
||||
"proxy-addr": "~2.0.5",
|
||||
"qs": "6.7.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"safe-buffer": "5.1.2",
|
||||
"send": "0.17.1",
|
||||
"serve-static": "1.14.1",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": "~1.5.0",
|
||||
"type-is": "~1.6.18",
|
||||
"utils-merge": "1.0.1",
|
||||
"vary": "~1.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"cookie": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
|
||||
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
|
||||
"accepts": {
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
||||
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
|
||||
"requires": {
|
||||
"mime-types": "~2.1.24",
|
||||
"negotiator": "0.6.2"
|
||||
}
|
||||
},
|
||||
"content-disposition": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
|
||||
"integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.2"
|
||||
}
|
||||
},
|
||||
"finalhandler": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
|
||||
"integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"on-finished": "~2.3.0",
|
||||
"parseurl": "~1.3.3",
|
||||
"statuses": "~1.5.0",
|
||||
"unpipe": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.7.3",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
|
||||
"integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
|
||||
"requires": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.0"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.43.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
|
||||
"integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.26",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
|
||||
"integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
|
||||
"requires": {
|
||||
"mime-db": "1.43.0"
|
||||
}
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
|
||||
},
|
||||
"parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
|
||||
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
|
||||
},
|
||||
"range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"send": {
|
||||
"version": "0.17.1",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
|
||||
"integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"destroy": "~1.0.4",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "~1.7.2",
|
||||
"mime": "1.6.0",
|
||||
"ms": "2.1.1",
|
||||
"on-finished": "~2.3.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"statuses": "~1.5.0"
|
||||
}
|
||||
},
|
||||
"serve-static": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
|
||||
"integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
|
||||
"requires": {
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"parseurl": "~1.3.3",
|
||||
"send": "0.17.1"
|
||||
}
|
||||
},
|
||||
"setprototypeof": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
|
||||
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
|
||||
},
|
||||
"type-is": {
|
||||
"version": "1.6.18",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
|
||||
"requires": {
|
||||
"media-typer": "0.3.0",
|
||||
"mime-types": "~2.1.24"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -16084,6 +16296,7 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
|
||||
"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"encodeurl": "~1.0.2",
|
||||
@@ -20265,9 +20478,9 @@
|
||||
"integrity": "sha512-pKnZpbgCTfH/1NLIlOduP/V+WRXzC2MOz3Qo8xmxk8C5GudJLgK5QyLVXOSWy3ParAH7Eemurl3xjv/WXYFvMA=="
|
||||
},
|
||||
"ipaddr.js": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz",
|
||||
"integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs="
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
|
||||
},
|
||||
"is-absolute": {
|
||||
"version": "1.0.0",
|
||||
@@ -26560,7 +26773,7 @@
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
|
||||
"resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz",
|
||||
"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
|
||||
"dev": true
|
||||
}
|
||||
@@ -29819,12 +30032,12 @@
|
||||
}
|
||||
},
|
||||
"proxy-addr": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz",
|
||||
"integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==",
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
|
||||
"integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
|
||||
"requires": {
|
||||
"forwarded": "~0.1.2",
|
||||
"ipaddr.js": "1.6.0"
|
||||
"ipaddr.js": "1.9.1"
|
||||
}
|
||||
},
|
||||
"proxy-agent": {
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@coralproject/talk",
|
||||
"version": "6.0.0",
|
||||
"version": "6.0.3",
|
||||
"author": "The Coral Project",
|
||||
"homepage": "https://coralproject.net/",
|
||||
"sideEffects": [
|
||||
@@ -83,7 +83,7 @@
|
||||
"dotenv": "^6.0.0",
|
||||
"dotenv-expand": "^4.2.0",
|
||||
"env-rewrite": "^1.0.2",
|
||||
"express": "^4.16.3",
|
||||
"express": "^4.17.1",
|
||||
"express-enforces-ssl": "^1.1.0",
|
||||
"express-static-gzip": "^0.3.2",
|
||||
"fs-extra": "^6.0.1",
|
||||
|
||||
@@ -155,6 +155,11 @@ const generateCookieOptions = (
|
||||
path: "/api",
|
||||
httpOnly: true,
|
||||
secure: req.secure,
|
||||
// Chrome will ignore `SameSite: None` when not used in a secure context
|
||||
// anyways, so don't bother setting `None` when we're not secure. The only
|
||||
// time we aren't behind HTTPS is when we're testing/in development where the
|
||||
// the setting for `SameSite: Lax` would be OK.
|
||||
sameSite: req.secure ? "None" : "Lax",
|
||||
expires: expiresIn,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import DataLoader from "dataloader";
|
||||
import { defaultTo } from "lodash";
|
||||
import { DateTime } from "luxon";
|
||||
|
||||
import GraphContext from "coral-server/graph/context";
|
||||
import { Connection } from "coral-server/models/helpers";
|
||||
import { CloseCommenting } from "coral-server/models/settings";
|
||||
import {
|
||||
retrieveActiveStories,
|
||||
retrieveManyStories,
|
||||
@@ -26,16 +28,89 @@ import {
|
||||
import { createManyBatchLoadFn } from "./util";
|
||||
|
||||
const statusFilter = (
|
||||
status?: GQLSTORY_STATUS
|
||||
closeCommenting: CloseCommenting,
|
||||
status?: GQLSTORY_STATUS,
|
||||
now = new Date()
|
||||
): StoryConnectionInput["filter"] => {
|
||||
switch (status) {
|
||||
case GQLSTORY_STATUS.OPEN:
|
||||
if (closeCommenting.auto) {
|
||||
// Automatic story closing has been enabled. Stories will be considered
|
||||
// open if they have a ${closedAt} date in the future, if they've been
|
||||
// forced open (where ${closedAt} is set to false), or they haven't been
|
||||
// closed and their ${createdAt} date is after ${now - close.timeout}.
|
||||
|
||||
// Calculate the cutoff time for createdAt.
|
||||
const consideredClosedAt = DateTime.fromJSDate(now)
|
||||
.plus({
|
||||
seconds: -closeCommenting.timeout,
|
||||
})
|
||||
.toJSDate();
|
||||
|
||||
return {
|
||||
$or: [
|
||||
// The story will be open if the close date is in the future...
|
||||
{
|
||||
closedAt: { $gt: now },
|
||||
},
|
||||
// Or the story has been forced open by setting closedAt to false...
|
||||
{
|
||||
closedAt: false,
|
||||
},
|
||||
// Or the closed at date isn't set and the createdAt date is after
|
||||
// the cutoff date.
|
||||
{
|
||||
closedAt: null,
|
||||
createdAt: { $gt: consideredClosedAt },
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
// Automatic story closing is not enabled. Stories will be considered open
|
||||
// if they do not have a ${closedAt}, it has been forced open (where
|
||||
// ${closedAt} is set to false), or the ${closedAt} date is in the future.
|
||||
return {
|
||||
closedAt: { $in: [null, false] },
|
||||
$or: [
|
||||
// A story is open if the closedAt date is in the future...
|
||||
{ closedAt: { $gt: now } },
|
||||
// Or the closedAt date is not set.
|
||||
{ closedAt: { $in: [null, false] } },
|
||||
],
|
||||
};
|
||||
case GQLSTORY_STATUS.CLOSED:
|
||||
if (closeCommenting.auto) {
|
||||
// Automatic story closing has been enabled. Stories will be considered
|
||||
// closed if they have a ${closedAt} date before the current date or
|
||||
// they do not have a ${closedAt} date set and the ${createdAt} date is
|
||||
// before ${now - close.timeout} (implying that it's close window is
|
||||
// up).
|
||||
|
||||
// Calculate the cutoff time for createdAt.
|
||||
const consideredClosedAt = DateTime.fromJSDate(now)
|
||||
.plus({
|
||||
seconds: -closeCommenting.timeout,
|
||||
})
|
||||
.toJSDate();
|
||||
|
||||
return {
|
||||
$or: [
|
||||
// The story will be closed if the closedAt date is in the past...
|
||||
{ closedAt: { $lte: now } },
|
||||
// Or the closedAt date isn't set and the createdAt date is before
|
||||
// the cutoff date.
|
||||
{
|
||||
closedAt: null,
|
||||
createdAt: { $lte: consideredClosedAt },
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
// Automatic story closing is not enabled. Stories will be considered
|
||||
// closed if the ${closedAt} date is before ${now}.
|
||||
return {
|
||||
closedAt: { $lte: new Date() },
|
||||
closedAt: { $lte: now },
|
||||
};
|
||||
default:
|
||||
return {};
|
||||
@@ -126,7 +201,7 @@ export default (ctx: GraphContext) => ({
|
||||
// Merge the site filter into the connection filter.
|
||||
...siteFilter(siteID),
|
||||
// Merge the status filter into the connection filter.
|
||||
...statusFilter(status),
|
||||
...statusFilter(ctx.tenant.closeCommenting, status, ctx.now),
|
||||
// Merge the query filters into the query.
|
||||
...queryFilter(query),
|
||||
},
|
||||
|
||||
@@ -1,29 +1,26 @@
|
||||
import { defaultsDeep } from "lodash";
|
||||
|
||||
import { decodeActionCounts } from "coral-server/models/action/comment";
|
||||
import * as story from "coral-server/models/story";
|
||||
|
||||
import {
|
||||
GQLSTORY_STATUS,
|
||||
GQLStoryTypeResolver,
|
||||
GQLTAG,
|
||||
} from "coral-server/graph/schema/__generated__/types";
|
||||
import { decodeActionCounts } from "coral-server/models/action/comment";
|
||||
import * as story from "coral-server/models/story";
|
||||
|
||||
import GraphContext from "../context";
|
||||
import { CommentCountsInput } from "./CommentCounts";
|
||||
import { storyModerationInputResolver } from "./ModerationQueues";
|
||||
|
||||
const isStoryClosed = (s: story.Story, ctx: GraphContext) => {
|
||||
const closedAt = story.getStoryClosedAt(ctx.tenant, s) || null;
|
||||
return !!closedAt && new Date() >= closedAt;
|
||||
};
|
||||
|
||||
export const Story: GQLStoryTypeResolver<story.Story> = {
|
||||
comments: (s, input, ctx) => ctx.loaders.Comments.forStory(s.id, input),
|
||||
featuredComments: (s, input, ctx) =>
|
||||
ctx.loaders.Comments.taggedForStory(s.id, GQLTAG.FEATURED, input),
|
||||
status: (s, input, ctx) =>
|
||||
isStoryClosed(s, ctx) ? GQLSTORY_STATUS.CLOSED : GQLSTORY_STATUS.OPEN,
|
||||
isClosed: (s, input, ctx) => isStoryClosed(s, ctx),
|
||||
story.isStoryClosed(ctx.tenant, s, ctx.now)
|
||||
? GQLSTORY_STATUS.CLOSED
|
||||
: GQLSTORY_STATUS.OPEN,
|
||||
isClosed: (s, input, ctx) => story.isStoryClosed(ctx.tenant, s, ctx.now),
|
||||
closedAt: (s, input, ctx) => story.getStoryClosedAt(ctx.tenant, s) || null,
|
||||
commentActionCounts: s => decodeActionCounts(s.commentCounts.action),
|
||||
commentCounts: (s): CommentCountsInput => s,
|
||||
|
||||
@@ -26,10 +26,19 @@ export function getStoryTitle(story: Pick<Story, "metadata" | "url">) {
|
||||
: story.url;
|
||||
}
|
||||
|
||||
export function isStoryClosed(
|
||||
tenant: Pick<Tenant, "closeCommenting">,
|
||||
story: Pick<Story, "closedAt" | "createdAt">,
|
||||
now = new Date()
|
||||
) {
|
||||
const closedAt = getStoryClosedAt(tenant, story);
|
||||
return !!closedAt && closedAt <= now;
|
||||
}
|
||||
|
||||
export function getStoryClosedAt(
|
||||
tenant: Pick<Tenant, "closeCommenting">,
|
||||
story: Pick<Story, "closedAt" | "createdAt">
|
||||
): Story["closedAt"] {
|
||||
): Date | null {
|
||||
// Try to get the closedAt time from the story.
|
||||
if (story.closedAt) {
|
||||
return story.closedAt;
|
||||
@@ -37,7 +46,7 @@ export function getStoryClosedAt(
|
||||
|
||||
// Check to see if the story has been forced open again.
|
||||
if (story.closedAt === false) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the story hasn't already been closed, then check to see if the Tenant
|
||||
@@ -50,5 +59,5 @@ export function getStoryClosedAt(
|
||||
.toJSDate();
|
||||
}
|
||||
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { StoryClosedError } from "coral-server/errors";
|
||||
import { getStoryClosedAt } from "coral-server/models/story";
|
||||
import { isStoryClosed } from "coral-server/models/story";
|
||||
import {
|
||||
IntermediatePhaseResult,
|
||||
ModerationPhaseContext,
|
||||
@@ -14,8 +14,7 @@ export const storyClosed = ({
|
||||
ModerationPhaseContext,
|
||||
"story" | "tenant" | "now"
|
||||
>): IntermediatePhaseResult | void => {
|
||||
const closedAt = getStoryClosedAt(tenant, story);
|
||||
if (closedAt && closedAt <= now) {
|
||||
if (isStoryClosed(tenant, story, now)) {
|
||||
throw new StoryClosedError();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
import {
|
||||
createSite,
|
||||
getURLOrigins,
|
||||
retrieveTenantSites,
|
||||
Site,
|
||||
updateSiteCounts,
|
||||
} from "coral-server/models/site";
|
||||
@@ -24,68 +25,99 @@ import Migration from "coral-server/services/migrate/migration";
|
||||
import collections from "coral-server/services/mongodb/collections";
|
||||
|
||||
import { MigrationError } from "../error";
|
||||
import { createIndexesFactory } from "../indexing";
|
||||
|
||||
interface OldTenant extends Tenant {
|
||||
allowedDomains: string[];
|
||||
}
|
||||
|
||||
async function findOrCreateSite(
|
||||
mongo: Db,
|
||||
tenant: Readonly<OldTenant>
|
||||
): Promise<Site> {
|
||||
// Get all the sites attached to this Tenant (if there are any).
|
||||
const sites = await retrieveTenantSites(mongo, tenant.id);
|
||||
if (sites && sites.length > 0) {
|
||||
// There was at least one site! If there is exactly one, then return it,
|
||||
// otherwise there is more than one site.
|
||||
if (sites.length === 1) {
|
||||
return sites[0];
|
||||
}
|
||||
|
||||
// There were more than 1 site! We can't handle this case.
|
||||
throw new Error("more than one site for this tenant is available");
|
||||
}
|
||||
|
||||
// Convert a tenant's domains into origins that we will re-use on the site.
|
||||
const allowedOrigins = getURLOrigins([
|
||||
...tenant.allowedDomains,
|
||||
tenant.domain,
|
||||
]);
|
||||
|
||||
return createSite(mongo, {
|
||||
tenantID: tenant.id,
|
||||
name: tenant.organization.name,
|
||||
allowedOrigins,
|
||||
});
|
||||
}
|
||||
|
||||
export default class extends Migration {
|
||||
private async createSite(mongo: Db, tenant: Readonly<OldTenant>) {
|
||||
const {
|
||||
organization: { name },
|
||||
domain,
|
||||
allowedDomains,
|
||||
} = tenant;
|
||||
private async findOrCreateSite(mongo: Db, tenant: Readonly<OldTenant>) {
|
||||
// Try to find the site.
|
||||
const site = await findOrCreateSite(mongo, tenant);
|
||||
|
||||
// Convert a tenant's domains into origins that we will re-use on the site.
|
||||
const allowedOrigins = getURLOrigins([...allowedDomains, domain]);
|
||||
|
||||
// Create the new site.
|
||||
const site = await createSite(mongo, {
|
||||
name,
|
||||
tenantID: tenant.id,
|
||||
allowedOrigins,
|
||||
});
|
||||
|
||||
this.logger.info({ site }, "created site");
|
||||
this.log(tenant.id).info("starting stories migration");
|
||||
|
||||
// Add the siteID to all the stories.
|
||||
let result = await collections
|
||||
.stories(mongo)
|
||||
.updateMany({ tenantID: tenant.id }, { $set: { siteID: site.id } });
|
||||
.updateMany(
|
||||
{ tenantID: tenant.id, siteID: null },
|
||||
{ $set: { siteID: site.id } }
|
||||
);
|
||||
|
||||
this.log(tenant.id).info(
|
||||
{
|
||||
matchedCount: result.matchedCount,
|
||||
modifiedCount: result.modifiedCount,
|
||||
},
|
||||
"added siteID to stories"
|
||||
"finished stories migration"
|
||||
);
|
||||
|
||||
this.log(tenant.id).info("starting comments migration");
|
||||
|
||||
// Add the siteID to all comments.
|
||||
result = await collections
|
||||
.comments(mongo)
|
||||
.updateMany({ tenantID: tenant.id }, { $set: { siteID: site.id } });
|
||||
.updateMany(
|
||||
{ tenantID: tenant.id, siteID: null },
|
||||
{ $set: { siteID: site.id } }
|
||||
);
|
||||
|
||||
this.log(tenant.id).info(
|
||||
{
|
||||
matchedCount: result.matchedCount,
|
||||
modifiedCount: result.modifiedCount,
|
||||
},
|
||||
"added siteID to comments"
|
||||
"finished comments migration"
|
||||
);
|
||||
|
||||
this.log(tenant.id).info("starting commentActions migration");
|
||||
|
||||
// Add the siteID to all commentActions.
|
||||
result = await collections
|
||||
.commentActions(mongo)
|
||||
.updateMany({ tenantID: tenant.id }, { $set: { siteID: site.id } });
|
||||
.updateMany(
|
||||
{ tenantID: tenant.id, siteID: null },
|
||||
{ $set: { siteID: site.id } }
|
||||
);
|
||||
|
||||
this.log(tenant.id).info(
|
||||
{
|
||||
matchedCount: result.matchedCount,
|
||||
modifiedCount: result.modifiedCount,
|
||||
},
|
||||
"added siteID to commentActions"
|
||||
"finished commentActions migration"
|
||||
);
|
||||
|
||||
return site;
|
||||
@@ -216,15 +248,8 @@ export default class extends Migration {
|
||||
]);
|
||||
}
|
||||
|
||||
// Try to find any site to see if this migration is needed.
|
||||
let site = await collections.sites(mongo).findOne({ tenantID });
|
||||
if (site) {
|
||||
this.log(tenantID).info({ site }, "site has already been created");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the site.
|
||||
site = await this.createSite(mongo, tenant);
|
||||
const site = await this.findOrCreateSite(mongo, tenant);
|
||||
|
||||
// Update the story action counts on the stories.
|
||||
await this.updateStoryActionCommentCounts(mongo, tenant);
|
||||
@@ -232,4 +257,17 @@ export default class extends Migration {
|
||||
// Update the site comment counts from the stories.
|
||||
await this.updateCommentCounts(mongo, tenant, site);
|
||||
}
|
||||
|
||||
public async indexes(mongo: Db) {
|
||||
// Create the indexes factory.
|
||||
const index = createIndexesFactory(mongo);
|
||||
|
||||
// Add indexes for { tenantID, siteID }.
|
||||
await index.comments({ tenantID: 1, siteID: 1 }, { background: true });
|
||||
await index.stories({ tenantID: 1, siteID: 1 }, { background: true });
|
||||
await index.commentActions(
|
||||
{ tenantID: 1, siteID: 1 },
|
||||
{ background: true }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user