From e5cf25d1796dc6d31b912d84981d9b31a6a4bfd4 Mon Sep 17 00:00:00 2001 From: nick-funk Date: Tue, 28 Nov 2023 16:08:15 -0700 Subject: [PATCH 1/2] set new fields to improve akismet spam payloads --- .../services/comments/pipeline/phases/spam.ts | 13 +++- server/src/core/server/services/spam/index.ts | 64 +++++++++++++++---- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/server/src/core/server/services/comments/pipeline/phases/spam.ts b/server/src/core/server/services/comments/pipeline/phases/spam.ts index e8d7a38014..f7a71c4052 100644 --- a/server/src/core/server/services/comments/pipeline/phases/spam.ts +++ b/server/src/core/server/services/comments/pipeline/phases/spam.ts @@ -6,6 +6,7 @@ import { IntermediateModerationPhase, IntermediatePhaseResult, } from "coral-server/services/comments/pipeline"; +import { AkismetSpamCheckPayload } from "coral-server/services/spam"; import { GQLCOMMENT_FLAG_REASON, @@ -20,6 +21,7 @@ export const spam: IntermediateModerationPhase = async ({ req, nudge, log, + now, }): Promise => { const integration = tenant.integrations.akismet; @@ -93,8 +95,9 @@ export const spam: IntermediateModerationPhase = async ({ try { log.trace("checking comment for spam"); - // Check the comment for spam. - const isSpam = await client.checkSpam({ + const payload: AkismetSpamCheckPayload = { + api_key: integration.key, + blog: integration.site, user_ip: userIP, // REQUIRED referrer, // REQUIRED user_agent: userAgent, // REQUIRED @@ -103,7 +106,11 @@ export const spam: IntermediateModerationPhase = async ({ comment_author: author.username || "", comment_type: "comment", is_test: false, - }); + comment_date_gmt: now.toISOString(), + }; + + // Check the comment for spam. + const isSpam = await client.checkSpam(payload); // NICK: make not any if (isSpam) { log.trace({ isSpam }, "comment contained spam"); diff --git a/server/src/core/server/services/spam/index.ts b/server/src/core/server/services/spam/index.ts index 557b18d6cd..9e4b710e3b 100644 --- a/server/src/core/server/services/spam/index.ts +++ b/server/src/core/server/services/spam/index.ts @@ -11,35 +11,74 @@ import { Request } from "coral-server/types/express"; export interface Parameters { apiKey: string; + blog: string; comment: Readonly; story: Readonly; author: Readonly; userIP: string | undefined; userAgent: string | undefined; referrer: string | undefined; + recheckReason?: string | undefined; } -const createBody = (params: Parameters) => { - const { comment, story, author, userIP, userAgent, referrer } = params; - const latestRevision = getLatestRevision(comment); - const username = author ? (author.username ? author.username : "") : ""; +export interface AkismetSpamCheckPayload { + api_key: string; + blog: string; + + user_ip: string; + user_agent: string; + referrer: string; + + permalink: string; + comment_type: string; + comment_author: string; + comment_content: string; + is_test: boolean; + comment_date_gmt: string; - return { - user_ip: userIP, - user_agent: userAgent, + recheck_reason?: string; +} + +const createBody = (params: Parameters): AkismetSpamCheckPayload => { + const { + comment, + story, + author, + userIP, + userAgent, referrer, + recheckReason, + apiKey, + blog, + } = params; + const latestRevision = getLatestRevision(comment); + + const body: AkismetSpamCheckPayload = { + api_key: apiKey, + blog, + + user_ip: userIP || "", + user_agent: userAgent || "", + referrer: referrer || "", permalink: story.url, comment_type: "comment", - comment_author: username, + comment_author: author?.username || "", comment_content: latestRevision ? latestRevision.body : "", - comment_date_gmt: latestRevision - ? latestRevision.createdAt.toISOString() - : "", is_test: false, + + comment_date_gmt: latestRevision + ? latestRevision.createdAt.toISOString() + : new Date().toISOString(), }; + + if (recheckReason) { + body.recheck_reason = recheckReason; + } + + return body; }; const submitSpam = async (params: Parameters) => { @@ -118,6 +157,7 @@ export const submitCommentAsNotSpam = async ( apiKey: tenant.integrations.akismet.key ? tenant.integrations.akismet.key : "", + blog: tenant.integrations.akismet.site || "", comment, story, author, @@ -161,11 +201,13 @@ export const submitCommentAsSpam = async ( apiKey: tenant.integrations.akismet.key ? tenant.integrations.akismet.key : "", + blog: tenant.integrations.akismet.site || "", comment, story, author, userIP, userAgent, referrer, + recheckReason: comment.revisions.length > 1 ? "edit" : undefined, }); }; From 22cebb9dc22741de90cf22bc83f4f59e5ff4fb0d Mon Sep 17 00:00:00 2001 From: nick-funk Date: Tue, 28 Nov 2023 16:27:26 -0700 Subject: [PATCH 2/2] upgrade akismet-api to v6 and use the new TS types --- server/package-lock.json | 500 ++++++++---------- server/package.json | 2 +- .../services/comments/pipeline/phases/spam.ts | 6 +- server/src/core/server/services/spam/index.ts | 36 +- server/src/types/akismet-api.d.ts | 33 -- 5 files changed, 233 insertions(+), 344 deletions(-) delete mode 100644 server/src/types/akismet-api.d.ts diff --git a/server/package-lock.json b/server/package-lock.json index 1f997418f3..b02ca27a94 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -24,7 +24,7 @@ "@types/url-regex-safe": "^1.0.0", "abort-controller": "^3.0.0", "address": "^1.2.2", - "akismet-api": "^5.0.0", + "akismet-api": "^6.0.0", "apollo-server-express": "^2.18.1", "apollo-server-plugin-base": "^0.10.1", "apollo-server-plugin-response-cache": "^0.5.5", @@ -10247,14 +10247,15 @@ "license": "MIT" }, "node_modules/akismet-api": { - "version": "5.0.0", - "license": "MIT", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/akismet-api/-/akismet-api-6.0.0.tgz", + "integrity": "sha512-IqPwdqKOpRXXJg/T2772BB1RoCFfB5kBX1Zeef98T/RkIIFuRqO1kPM4wAjgIdGtvP7YNQ8VYh9kTszpR0637g==", "dependencies": { "bluebird": "^3.1.1", - "superagent": "^5.1.1" + "superagent": "^8.0.0" }, "engines": { - "node": ">=4.0.0" + "node": ">=14.0.0" } }, "node_modules/alphanum-sort": { @@ -13864,7 +13865,6 @@ }, "node_modules/call-bind": { "version": "1.0.2", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.1", @@ -14847,9 +14847,12 @@ "license": "MIT" }, "node_modules/component-emitter": { - "version": "1.2.1", - "dev": true, - "license": "MIT" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/component-type": { "version": "1.2.1", @@ -15209,8 +15212,9 @@ "license": "MIT" }, "node_modules/cookiejar": { - "version": "2.1.2", - "license": "MIT" + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==" }, "node_modules/copy-concurrently": { "version": "1.0.5", @@ -17751,6 +17755,15 @@ "dev": true, "license": "ISC" }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, "node_modules/dicer": { "version": "0.3.0", "dependencies": { @@ -18736,14 +18749,6 @@ "node": ">=4.0" } }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/object-inspect": { - "version": "1.9.0", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/eslint-plugin-jsx-a11y/node_modules/object.assign": { "version": "4.1.2", "dev": true, @@ -20351,8 +20356,9 @@ "license": "MIT" }, "node_modules/fast-safe-stringify": { - "version": "2.0.7", - "license": "MIT" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, "node_modules/fast-shallow-equal": { "version": "1.0.0", @@ -20951,8 +20957,32 @@ } }, "node_modules/formidable": { - "version": "1.2.1", - "license": "MIT" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", + "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", + "dependencies": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0", + "qs": "^6.11.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/formidable/node_modules/qs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", + "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/forwarded": { "version": "0.1.2", @@ -22037,7 +22067,6 @@ }, "node_modules/get-intrinsic": { "version": "1.1.0", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.1", @@ -22050,7 +22079,6 @@ }, "node_modules/get-intrinsic/node_modules/has-symbols": { "version": "1.0.1", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -24509,6 +24537,14 @@ "dev": true, "license": "MIT" }, + "node_modules/hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "engines": { + "node": ">=8" + } + }, "node_modules/hide-powered-by": { "version": "1.1.0", "license": "MIT", @@ -33978,8 +34014,9 @@ } }, "node_modules/object-inspect": { - "version": "1.7.0", - "license": "MIT", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -41415,14 +41452,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regexp.prototype.flags/node_modules/object-inspect": { - "version": "1.7.0", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/regexpp": { "version": "3.1.0", "dev": true, @@ -42693,115 +42722,18 @@ "license": "MIT" }, "node_modules/side-channel": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "es-abstract": "^1.17.0-next.1", - "object-inspect": "^1.7.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel/node_modules/es-abstract": { - "version": "1.17.6", - "dev": true, - "license": "MIT", - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel/node_modules/es-to-primitive": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel/node_modules/has-symbols": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel/node_modules/is-callable": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel/node_modules/is-regex": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel/node_modules/is-symbol": { - "version": "1.0.3", - "dev": true, - "license": "MIT", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/side-channel/node_modules/object-keys": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/signal-exit": { "version": "3.0.2", "license": "ISC" @@ -44409,39 +44341,45 @@ } }, "node_modules/superagent": { - "version": "5.2.1", - "license": "MIT", + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", + "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", "dependencies": { "component-emitter": "^1.3.0", - "cookiejar": "^2.1.2", - "debug": "^4.1.1", - "fast-safe-stringify": "^2.0.7", - "form-data": "^3.0.0", - "formidable": "^1.2.1", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.1.2", "methods": "^1.1.2", - "mime": "^2.4.4", - "qs": "^6.9.1", - "readable-stream": "^3.4.0", - "semver": "^6.3.0" + "mime": "2.6.0", + "qs": "^6.11.0", + "semver": "^7.3.8" }, "engines": { - "node": ">= 7.0.0" + "node": ">=6.4.0 <13 || >=14" } }, - "node_modules/superagent/node_modules/component-emitter": { - "version": "1.3.0", - "license": "MIT" - }, "node_modules/superagent/node_modules/debug": { - "version": "4.1.1", - "license": "MIT", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "ms": "^2.1.1" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/superagent/node_modules/form-data": { - "version": "3.0.0", - "license": "MIT", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -44451,9 +44389,24 @@ "node": ">= 6" } }, + "node_modules/superagent/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/superagent/node_modules/qs": { - "version": "6.9.1", - "license": "BSD-3-Clause", + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", + "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "dependencies": { + "side-channel": "^1.0.4" + }, "engines": { "node": ">=0.6" }, @@ -44461,25 +44414,25 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/superagent/node_modules/readable-stream": { - "version": "3.5.0", - "license": "MIT", + "node_modules/superagent/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "lru-cache": "^6.0.0" }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/superagent/node_modules/semver": { - "version": "6.3.0", - "license": "ISC", "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, + "node_modules/superagent/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/supports-color": { "version": "2.0.0", "dev": true, @@ -56846,10 +56799,12 @@ "requires": {} }, "akismet-api": { - "version": "5.0.0", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/akismet-api/-/akismet-api-6.0.0.tgz", + "integrity": "sha512-IqPwdqKOpRXXJg/T2772BB1RoCFfB5kBX1Zeef98T/RkIIFuRqO1kPM4wAjgIdGtvP7YNQ8VYh9kTszpR0637g==", "requires": { "bluebird": "^3.1.1", - "superagent": "^5.1.1" + "superagent": "^8.0.0" } }, "alphanum-sort": { @@ -59480,7 +59435,6 @@ }, "call-bind": { "version": "1.0.2", - "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -60200,8 +60154,9 @@ "dev": true }, "component-emitter": { - "version": "1.2.1", - "dev": true + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==" }, "component-type": { "version": "1.2.1" @@ -60440,7 +60395,9 @@ "version": "1.0.6" }, "cookiejar": { - "version": "2.1.2" + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==" }, "copy-concurrently": { "version": "1.0.5", @@ -62199,6 +62156,15 @@ "version": "2.0.4", "dev": true }, + "dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, "dicer": { "version": "0.3.0", "requires": { @@ -63073,10 +63039,6 @@ "object.assign": "^4.1.2" } }, - "object-inspect": { - "version": "1.9.0", - "dev": true - }, "object.assign": { "version": "4.1.2", "dev": true, @@ -63972,7 +63934,9 @@ "version": "2.0.6" }, "fast-safe-stringify": { - "version": "2.0.7" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, "fast-shallow-equal": { "version": "1.0.0", @@ -64393,7 +64357,25 @@ "dev": true }, "formidable": { - "version": "1.2.1" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", + "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", + "requires": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0", + "qs": "^6.11.0" + }, + "dependencies": { + "qs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", + "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "requires": { + "side-channel": "^1.0.4" + } + } + } }, "forwarded": { "version": "0.1.2" @@ -65231,7 +65213,6 @@ }, "get-intrinsic": { "version": "1.1.0", - "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -65239,8 +65220,7 @@ }, "dependencies": { "has-symbols": { - "version": "1.0.1", - "dev": true + "version": "1.0.1" } } }, @@ -67046,6 +67026,11 @@ "version": "1.1.0", "dev": true }, + "hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==" + }, "hide-powered-by": { "version": "1.1.0" }, @@ -73403,7 +73388,9 @@ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==" }, "object-inspect": { - "version": "1.7.0" + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==" }, "object-is": { "version": "1.0.1", @@ -78518,10 +78505,6 @@ "requires": { "has-symbols": "^1.0.1" } - }, - "object-inspect": { - "version": "1.7.0", - "dev": true } } }, @@ -79413,65 +79396,13 @@ "dev": true }, "side-channel": { - "version": "1.0.2", - "dev": true, + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "requires": { - "es-abstract": "^1.17.0-next.1", - "object-inspect": "^1.7.0" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "dev": true - }, - "is-callable": { - "version": "1.2.0", - "dev": true - }, - "is-regex": { - "version": "1.1.0", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-symbol": { - "version": "1.0.3", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-keys": { - "version": "1.1.1", - "dev": true - } + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" } }, "signal-exit": { @@ -80595,51 +80526,68 @@ } }, "superagent": { - "version": "5.2.1", + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", + "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", "requires": { "component-emitter": "^1.3.0", - "cookiejar": "^2.1.2", - "debug": "^4.1.1", - "fast-safe-stringify": "^2.0.7", - "form-data": "^3.0.0", - "formidable": "^1.2.1", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.1.2", "methods": "^1.1.2", - "mime": "^2.4.4", - "qs": "^6.9.1", - "readable-stream": "^3.4.0", - "semver": "^6.3.0" + "mime": "2.6.0", + "qs": "^6.11.0", + "semver": "^7.3.8" }, "dependencies": { - "component-emitter": { - "version": "1.3.0" - }, "debug": { - "version": "4.1.1", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "form-data": { - "version": "3.0.0", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } }, - "qs": { - "version": "6.9.1" + "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" + } }, - "readable-stream": { - "version": "3.5.0", + "qs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", + "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "side-channel": "^1.0.4" } }, "semver": { - "version": "6.3.0" + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "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==" } } }, diff --git a/server/package.json b/server/package.json index 7ca894b53c..4de875ea17 100644 --- a/server/package.json +++ b/server/package.json @@ -67,7 +67,7 @@ "@types/url-regex-safe": "^1.0.0", "abort-controller": "^3.0.0", "address": "^1.2.2", - "akismet-api": "^5.0.0", + "akismet-api": "^6.0.0", "apollo-server-express": "^2.18.1", "apollo-server-plugin-base": "^0.10.1", "apollo-server-plugin-response-cache": "^0.5.5", diff --git a/server/src/core/server/services/comments/pipeline/phases/spam.ts b/server/src/core/server/services/comments/pipeline/phases/spam.ts index f7a71c4052..60679d06cb 100644 --- a/server/src/core/server/services/comments/pipeline/phases/spam.ts +++ b/server/src/core/server/services/comments/pipeline/phases/spam.ts @@ -1,4 +1,4 @@ -import { Client } from "akismet-api"; +import { AkismetClient } from "akismet-api"; import { SpamCommentError } from "coral-server/errors"; import { ACTION_TYPE } from "coral-server/models/action/comment"; @@ -57,7 +57,7 @@ export const spam: IntermediateModerationPhase = async ({ } // Create the Akismet client. - const client = new Client({ + const client = new AkismetClient({ key: integration.key, blog: integration.site, }); @@ -96,8 +96,6 @@ export const spam: IntermediateModerationPhase = async ({ log.trace("checking comment for spam"); const payload: AkismetSpamCheckPayload = { - api_key: integration.key, - blog: integration.site, user_ip: userIP, // REQUIRED referrer, // REQUIRED user_agent: userAgent, // REQUIRED diff --git a/server/src/core/server/services/spam/index.ts b/server/src/core/server/services/spam/index.ts index 9e4b710e3b..1d56d1eb66 100644 --- a/server/src/core/server/services/spam/index.ts +++ b/server/src/core/server/services/spam/index.ts @@ -9,6 +9,8 @@ import { Tenant } from "coral-server/models/tenant"; import { retrieveUser } from "coral-server/models/user"; import { Request } from "coral-server/types/express"; +import { Comment as AkismetComment } from "akismet-api"; + export interface Parameters { apiKey: string; blog: string; @@ -21,42 +23,16 @@ export interface Parameters { recheckReason?: string | undefined; } -export interface AkismetSpamCheckPayload { - api_key: string; - blog: string; - - user_ip: string; - user_agent: string; - referrer: string; - - permalink: string; - comment_type: string; - comment_author: string; - comment_content: string; - is_test: boolean; - comment_date_gmt: string; - +export type AkismetSpamCheckPayload = AkismetComment & { recheck_reason?: string; -} +}; const createBody = (params: Parameters): AkismetSpamCheckPayload => { - const { - comment, - story, - author, - userIP, - userAgent, - referrer, - recheckReason, - apiKey, - blog, - } = params; + const { comment, story, author, userIP, userAgent, referrer, recheckReason } = + params; const latestRevision = getLatestRevision(comment); const body: AkismetSpamCheckPayload = { - api_key: apiKey, - blog, - user_ip: userIP || "", user_agent: userAgent || "", referrer: referrer || "", diff --git a/server/src/types/akismet-api.d.ts b/server/src/types/akismet-api.d.ts deleted file mode 100644 index a6d6a44759..0000000000 --- a/server/src/types/akismet-api.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -declare module "akismet-api" { - export interface ClientOptions { - key: string; - blog: string; - } - - export interface CheckSpamOptions { - user_ip: string; - user_agent: string; - referrer: string; - permalink?: string; - comment_type?: string; - comment_author?: string; - comment_content?: string; - comment_author_url?: string; - comment_author_email?: string; - comment_date_gmt?: string; - comment_post_modified_gmt?: string; - user_role?: string; - is_test?: boolean; - } - - export class Client { - constructor(options: ClientOptions) - - /** - * checkSpam will check the given comment payload for spam. - * - * @param options used to provide the input for checking spam - */ - checkSpam(options: CheckSpamOptions): Promise - } -} \ No newline at end of file