diff --git a/package-lock.json b/package-lock.json index 29e670a4a..a37454437 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4328,44 +4328,6 @@ "resolved": "https://registry.npmjs.org/csextends/-/csextends-1.2.0.tgz", "integrity": "sha512-S/8k1bDTJIwuGgQYmsRoE+8P+ohV32WhQ0l4zqrc0XDdxOhjQQD7/wTZwCzoZX53jSX3V/qwjT+OkPTxWQcmjg==" }, - "csrf": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", - "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", - "requires": { - "rndm": "1.2.0", - "tsscmp": "1.0.5", - "uid-safe": "2.1.4" - } - }, - "csurf": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.9.0.tgz", - "integrity": "sha1-SdLGkl/87Ht95VlZfBU/pTM2QTM=", - "requires": { - "cookie": "0.3.1", - "cookie-signature": "1.0.6", - "csrf": "~3.0.3", - "http-errors": "~1.5.0" - }, - "dependencies": { - "http-errors": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz", - "integrity": "sha1-eIwNLB3iyBuebowBhDtrl+uSB1A=", - "requires": { - "inherits": "2.0.3", - "setprototypeof": "1.0.2", - "statuses": ">= 1.3.1 < 2" - } - }, - "setprototypeof": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz", - "integrity": "sha1-gaVSFB7BBLiOic44MQOtXGZWTQg=" - } - } - }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -6732,13 +6694,25 @@ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, "requires": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", "mime-types": "^2.1.12" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + } } }, "forwarded": { @@ -12164,11 +12138,6 @@ "integrity": "sha1-zNE//3NJepOXTj6GMnv9h71ujis=", "dev": true }, - "random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" - }, "randombytes": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", @@ -12489,7 +12458,6 @@ "combined-stream": "~1.0.6", "extend": "~3.0.2", "forever-agent": "~0.6.1", - "form-data": "~2.3.2", "har-validator": "~5.1.0", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", @@ -12645,11 +12613,6 @@ "safe-buffer": "^5.1.1" } }, - "rndm": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", - "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" - }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", @@ -14303,11 +14266,6 @@ "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", "dev": true }, - "tsscmp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", - "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=" - }, "tty-browserify": { "version": "0.0.0", "resolved": "http://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -14378,14 +14336,6 @@ "is-typedarray": "^1.0.0" } }, - "uid-safe": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", - "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", - "requires": { - "random-bytes": "~1.0.0" - } - }, "uid2": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", diff --git a/package.json b/package.json index d3228f9dd..1b1f39528 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,6 @@ "cookie-parser": "^1.4.3", "cors": "^2.8.5", "create-hash": "^1.2.0", - "csurf": "^1.9.0", "disposable-email-domains": "^1.0.56", "eth-sig-util": "^1.4.2", "express": "^4.17.0", diff --git a/src/constant/index.js b/src/constant/index.js index 0d6d9e30d..24217144a 100644 --- a/src/constant/index.js +++ b/src/constant/index.js @@ -119,11 +119,6 @@ export const BUTTON_COOKIE_OPTION = { sameSite: TEST_MODE ? false : 'none', }; -export const CSRF_COOKIE_OPTION = { - httpOnly: true, - secure: process.env.NODE_ENV === 'production', -}; - // TODO: duplicate with ../../constant.js export const W3C_EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/; export const EMAIL_REGEX = IS_TESTNET ? /.*/ : W3C_EMAIL_REGEX; diff --git a/src/middleware/errorHandler.js b/src/middleware/errorHandler.js index e5417380b..f4c639c1e 100644 --- a/src/middleware/errorHandler.js +++ b/src/middleware/errorHandler.js @@ -22,9 +22,6 @@ export default function errorHandler(err, req, res, next) { if (err.code === 'LIMIT_FILE_SIZE') { return res.status(400).send('FILE_TOO_LARGE'); } - if (err.code === 'EBADCSRFTOKEN') { - return res.status(400).send('BAD_CSRF_TOKEN'); - } } return res.sendStatus(500); } diff --git a/src/routes/users/registerLogin.js b/src/routes/users/registerLogin.js index c958be5dd..30e3723e3 100644 --- a/src/routes/users/registerLogin.js +++ b/src/routes/users/registerLogin.js @@ -1,8 +1,5 @@ import { Router } from 'express'; -import bodyParser from 'body-parser'; -import csrf from 'csurf'; import { - CSRF_COOKIE_OPTION, PUBSUB_TOPIC_MISC, TEST_MODE, } from '../../constant'; @@ -24,10 +21,7 @@ import { normalizeUserEmail, getUserAgentIsApp, } from '../../util/api/users'; -import { - handleUserRegistration, - getAvatarUrl, -} from '../../util/api/users/register'; +import { handleUserRegistration } from '../../util/api/users/register'; import { handleAppReferrer, handleUpdateAppMetaData } from '../../util/api/users/app'; import { ValidationError } from '../../util/ValidationError'; import { handleAvatarUploadAndGetURL } from '../../util/fileupload'; @@ -69,36 +63,8 @@ const apiLimiter = new RateLimit({ router.use(loginPlatforms); -function csrfCheck(req, res, next) { - const { 'user-agent': userAgent = '' } = req.headers; - if (userAgent.includes('LikeCoinApp')) { - next(); - } else { - csrf({ cookie: CSRF_COOKIE_OPTION })(req, res, next); - } -} - -// deprecated -function isJson(req) { - return !!req.is('application/json'); -} - -// deprecated -function loadMiddlewareByContentType(req, res, next) { - if (!isJson(req)) { - csrfCheck(req, res, (csrfErr) => { - if (csrfErr) next(csrfErr); - bodyParser.urlencoded({ extended: false })(req, res, (bpErr) => { - if (bpErr) next(bpErr); - multer.single('avatarFile')(req, res, next); - }); - }); - } else next(); -} - router.post( '/new', - loadMiddlewareByContentType, // deprecated apiLimiter, async (req, res, next) => { const { @@ -226,7 +192,6 @@ router.post( router.post( '/update', jwtAuth('write'), - loadMiddlewareByContentType, // deprecated async (req, res, next) => { try { const { user } = req.user; @@ -252,21 +217,12 @@ router.post( locale: oldLocale, } = oldUserObj.data(); - // update avatar const updateObj = { displayName, isEmailEnabled, locale, }; - // deprecated - let avatarUrl; - const isLegacyReq = !isJson(req); - if (isLegacyReq) { - avatarUrl = await getAvatarUrl(req, user); - updateObj.avatar = avatarUrl; - } - if (!oldEmail && email) { await userByEmailQuery(user, email); updateObj.email = email; @@ -299,7 +255,7 @@ router.post( email: email || oldEmail, displayName: displayName || oldDisplayName, wallet, - avatar: avatarUrl || avatar, + avatar, referrer, locale: locale || oldLocale, registerTime: timestamp, diff --git a/src/util/api/users/register.js b/src/util/api/users/register.js index 80b771dc2..6200bb9ad 100644 --- a/src/util/api/users/register.js +++ b/src/util/api/users/register.js @@ -301,20 +301,3 @@ export async function handleUserRegistration({ socialPayload, }; } - -// deprecated -export async function getAvatarUrl(req, user) { - const { file } = req; - const { avatarSHA256 } = req.body; - let avatarUrl; - if (file) { - try { - avatarUrl = await handleAvatarUploadAndGetURL(user, file, avatarSHA256); - } catch (err) { - console.error('Avatar file handling error:'); - console.error(err); - throw new ValidationError('INVALID_AVATAR'); - } - } - return avatarUrl; -} diff --git a/test/api/user.test.js b/test/api/user.test.js index 6a038d4be..fbfe84efa 100644 --- a/test/api/user.test.js +++ b/test/api/user.test.js @@ -53,7 +53,7 @@ test.serial('USER: Login user. Case: success', async (t) => { t.is(res.status, 200); }); -test.serial('USER: Edit user by JSON. Case: success', async (t) => { +test.serial('USER: Edit user. Case: success', async (t) => { const user = testingUser1; const token = jwtSign({ user }); const payload = { @@ -72,7 +72,7 @@ test.serial('USER: Edit user by JSON. Case: success', async (t) => { t.is(res.status, 200); }); -test.serial('USER: Edit user by form-data. Case: success', async (t) => { +test.serial('USER: Edit user by form-data. Case: invalid content type', async (t) => { const user = testingUser1; const token = jwtSign({ user }); const payload = new FormData(); @@ -83,34 +83,13 @@ test.serial('USER: Edit user by form-data. Case: success', async (t) => { payload.append('email', 'noreply@likecoin.store'); const res = await axiosist.post('/api/users/update', payload, { headers: { - Cookie: `likecoin_auth=${token}; _csrf=unit_test`, - 'x-csrf-token': '73fb9061-W0SmQvlNKd0uKS4d2nKoZd0u7SA', - ...payload.getHeaders(), - }, - }); - - t.is(res.status, 200); -}); - -test.serial('USER: Edit user by form-data. Case: invalid csrf token', async (t) => { - const user = testingUser1; - const token = jwtSign({ user }); - const payload = new FormData(); - payload.append('user', user); - payload.append('displayName', testingDisplayName1); - payload.append('ts', Date.now()); - payload.append('wallet', testingWallet1); - payload.append('email', 'noreply@likecoin.store'); - const res = await axiosist.post('/api/users/update', payload, { - headers: { - Cookie: `likecoin_auth=${token}; _csrf=unit_test`, - 'x-csrf-token': 'invalid-token', + Cookie: `likecoin_auth=${token};`, ...payload.getHeaders(), }, }).catch(err => err.response); t.is(res.status, 400); - t.is(res.data, 'BAD_CSRF_TOKEN'); + t.is(res.data, 'INVALID_PAYLOAD'); }); test.serial('USER: Update avatar. Case: success', async (t) => { @@ -324,11 +303,6 @@ for (let i = 0; i < userCases.length; i += 1) { payload: formatedPayload, sign, platform: 'wallet', - }, { - headers: { - Cookie: '_csrf=unit_test', - 'x-csrf-token': '73fb9061-W0SmQvlNKd0uKS4d2nKoZd0u7SA', - }, }).catch(err => err.response); t.is(res.status, 400);