From d3f37d0bbcaed278b31ac797973ff6b23015b6f7 Mon Sep 17 00:00:00 2001 From: Viachaslau Tyshkavets Date: Mon, 26 Aug 2024 16:08:18 +0400 Subject: [PATCH] refactor: fix eslint violations --- .eslintrc.js | 2 -- .github/workflows/check.yml | 7 +++--- src/app.controller.ts | 6 ++--- src/auth/auth.service.ts | 6 ----- .../jwt/jwt.token.with.sql.kid.processor.ts | 2 +- .../jwt/jwt.token.with.x5c.key.processor.ts | 2 +- .../jwt/jwt.token.with.x5u.key.processor.ts | 2 +- .../headers.configurator.interceptor.ts | 1 - src/email/email.controller.ts | 7 +++--- src/email/email.service.ts | 22 +++++++--------- src/file/file.controller.ts | 1 - src/partners/partners.controller.ts | 16 ++++++------ src/partners/partners.service.ts | 15 ++++++----- src/products/products.controller.ts | 1 - src/users/users.controller.ts | 1 - src/users/users.service.ts | 2 +- src/utils/url.ts | 25 +++++++++---------- 17 files changed, 49 insertions(+), 69 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 885ece70..6940fdde 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -17,8 +17,6 @@ module.exports = { jest: true, }, rules: { - '@typescript-eslint/interface-name-prefix': 'off', - '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/no-explicit-any': 'off', }, diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index dfca7deb..3d244b45 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -19,7 +19,7 @@ concurrency: cancel-in-progress: true jobs: - test: + check: runs-on: ubuntu-latest strategy: matrix: @@ -39,9 +39,8 @@ jobs: - name: Check format run: npm run format - # commented till fixing lint errors - # - name: Lint - # run: npm run lint + - name: Lint + run: npm run lint - name: Build run: npm run build diff --git a/src/app.controller.ts b/src/app.controller.ts index 26501560..47fd3ad1 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -184,7 +184,7 @@ export class AppController { type: Object, status: 200, }) - getSecrets(): Object { + getSecrets(): Record { const secrets = { codeclimate: 'CODECLIMATE_REPO_TOKEN=62864c476ade6ab9d10d0ce0901ae2c211924852a28c5f960ae5165c1fdfec73', @@ -290,8 +290,8 @@ export class AppController { this.logger.debug(`Creating a JSON with a nesting depth of ${depth}`); - var tmpObj: object = {}; - var jsonObj: object = { '0': 'Leaf' }; + let tmpObj = {}; + let jsonObj: Record = { '0': 'Leaf' }; for (let i = 1; i < depth; i++) { tmpObj = {}; tmpObj[i.toString()] = Object.assign({}, jsonObj); diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index ad752dd6..5ae1688d 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -58,12 +58,6 @@ export class AuthService { ), 'utf8', ); - const jwkPublicKey = fs.readFileSync( - this.configService.get( - AuthModuleConfigProperties.ENV_JWK_PUBLIC_KEY_LOCATION, - ), - 'utf8', - ); const jwkPublicJson = JSON.parse( fs.readFileSync( this.configService.get( diff --git a/src/auth/jwt/jwt.token.with.sql.kid.processor.ts b/src/auth/jwt/jwt.token.with.sql.kid.processor.ts index 4056128d..ef893e31 100644 --- a/src/auth/jwt/jwt.token.with.sql.kid.processor.ts +++ b/src/auth/jwt/jwt.token.with.sql.kid.processor.ts @@ -16,7 +16,7 @@ export class JwtTokenWithSqlKIDProcessor extends JwtTokenProcessor { async validateToken(token: string): Promise { this.log.debug('Call validateToken'); - const [header, payload] = this.parse(token); + const [header] = this.parse(token); const query = JwtTokenWithSqlKIDProcessor.KID_FETCH_QUERY( this.key, diff --git a/src/auth/jwt/jwt.token.with.x5c.key.processor.ts b/src/auth/jwt/jwt.token.with.x5c.key.processor.ts index ab8c0f49..c5090c5b 100644 --- a/src/auth/jwt/jwt.token.with.x5c.key.processor.ts +++ b/src/auth/jwt/jwt.token.with.x5c.key.processor.ts @@ -9,7 +9,7 @@ export class JwtTokenWithX5CKeyProcessor extends JwtTokenProcessor { async validateToken(token: string): Promise { this.log.debug('Call validateToken'); - const [header, payload] = this.parse(token); + const [header] = this.parse(token); const keys = header.x5c; const keyLike = await jose.importPKCS8(keys[0], 'RS256'); diff --git a/src/auth/jwt/jwt.token.with.x5u.key.processor.ts b/src/auth/jwt/jwt.token.with.x5u.key.processor.ts index 764d9a75..90c30c28 100644 --- a/src/auth/jwt/jwt.token.with.x5u.key.processor.ts +++ b/src/auth/jwt/jwt.token.with.x5u.key.processor.ts @@ -13,7 +13,7 @@ export class JwtTokenWithX5UKeyProcessor extends JwtTokenProcessor { async validateToken(token: string): Promise { this.log.debug('Call validateToken'); - const [header, payload] = this.parse(token); + const [header] = this.parse(token); const url = header.x5u; this.log.debug(`Loading key from url ${url}`); diff --git a/src/components/headers.configurator.interceptor.ts b/src/components/headers.configurator.interceptor.ts index 4a69bc92..9be12948 100644 --- a/src/components/headers.configurator.interceptor.ts +++ b/src/components/headers.configurator.interceptor.ts @@ -2,7 +2,6 @@ import { CallHandler, ExecutionContext, Injectable, - InternalServerErrorException, Logger, NestInterceptor, } from '@nestjs/common'; diff --git a/src/email/email.controller.ts b/src/email/email.controller.ts index 6334b7e0..afcbc787 100644 --- a/src/email/email.controller.ts +++ b/src/email/email.controller.ts @@ -17,7 +17,6 @@ import { SWAGGER_DESC_SEND_EMAIL, } from './email.controller.swagger.desc'; import splitUriIntoParamsPPVulnerable from '../utils/url'; -import { boolean } from 'webidl-conversions'; @Controller('/api/email') @ApiTags('Emails controller') @@ -64,7 +63,7 @@ export class EmailController { this.logger.log('Sending a support Email'); // This is defined here intentionally so we don't override responseJson.status after the prototype pollution has occurred - let responseJson = { + const responseJson = { message: {}, status: HttpStatus.OK, }; @@ -85,14 +84,14 @@ export class EmailController { this.logger.debug(`Raw query ${rawQuery}`); // "Use" the status code - let uriParams: any = splitUriIntoParamsPPVulnerable(rawQuery); + const uriParams: any = splitUriIntoParamsPPVulnerable(rawQuery); if (uriParams?.status) { responseJson.status = uriParams.status; } const mailSubject = `Support email regarding "${subject}"`; const mailBody = `Hi ${name},\nWe recieved your email and just wanted to let you know we're on it!\n\nYour original inquiry was:\n**********************\n${content}\n**********************`; - let didSucceed = await this.emailService.sendRawEmail( + const didSucceed = await this.emailService.sendRawEmail( this.BC_EMAIL_ADDRESS, to, mailSubject, diff --git a/src/email/email.service.ts b/src/email/email.service.ts index 03a934d8..e577c208 100644 --- a/src/email/email.service.ts +++ b/src/email/email.service.ts @@ -1,9 +1,7 @@ -const axios = require('axios'); - +import axios from 'axios'; import { HttpStatus, Injectable, Logger } from '@nestjs/common'; -import { forEach } from 'lodash'; import { json } from 'sequelize'; -const nodemailer = require('nodemailer'); +import { createTransport } from 'nodemailer'; @Injectable() export class EmailService { @@ -19,9 +17,7 @@ export class EmailService { }, }; - private readonly transporter = nodemailer.createTransport( - this.smtpServerDetails, - ); + private readonly transporter = createTransport(this.smtpServerDetails); private readonly MAIL_CATCHER_MESSAGES_URL = 'http://mailcatcher:1080/messages'; @@ -45,7 +41,7 @@ export class EmailService { body, ); - let response = await this.transporter.sendMail(mailOptions); + const response = await this.transporter.sendMail(mailOptions); if (response.err) { this.logger.debug(`Failed sending email. Error: ${response.err}`); @@ -116,7 +112,7 @@ export class EmailService { rawContent += `\n${body}\n`; - let mailOptions = { + const mailOptions = { envelope: { from: parsedFrom, to: parsedTo, @@ -132,7 +128,7 @@ export class EmailService { async getEmails(withSource): Promise { this.logger.debug(`Fetching all emails from MailCatcher`); - let emails = await axios + const emails = await axios .get(this.MAIL_CATCHER_MESSAGES_URL) .then((res) => res.status == HttpStatus.OK @@ -142,7 +138,7 @@ export class EmailService { if (withSource) { this.logger.debug(`Fetching sources of Emails`); - for (let email of emails) { + for (const email of emails) { email['source'] = await this.getEmailSource(email['id']); } } @@ -151,7 +147,7 @@ export class EmailService { } private async getEmailSource(emailId): Promise { - let sourceUrl = `${this.MAIL_CATCHER_MESSAGES_URL}/${emailId}.source`; + const sourceUrl = `${this.MAIL_CATCHER_MESSAGES_URL}/${emailId}.source`; return await axios .get(sourceUrl) @@ -167,7 +163,7 @@ export class EmailService { ); } - async deleteEmails(): Promise { + async deleteEmails(): Promise { this.logger.debug(`Deleting all emails from MailCatcher`); return await axios diff --git a/src/file/file.controller.ts b/src/file/file.controller.ts index 2f8aae4a..388c8a54 100644 --- a/src/file/file.controller.ts +++ b/src/file/file.controller.ts @@ -4,7 +4,6 @@ import { Controller, Delete, Get, - Headers, HttpStatus, Logger, Put, diff --git a/src/partners/partners.controller.ts b/src/partners/partners.controller.ts index 2776fbc6..8ff5af85 100644 --- a/src/partners/partners.controller.ts +++ b/src/partners/partners.controller.ts @@ -42,7 +42,7 @@ export class PartnersController { @ApiOkResponse({ type: String, }) - async queryPartnersRaw(@Query('xpath') xpath: string): Promise { + async queryPartnersRaw(@Query('xpath') xpath: string): Promise { this.logger.debug(`Getting partners with xpath expression "${xpath}"`); try { @@ -79,14 +79,14 @@ export class PartnersController { async partnerLogin( @Query('username') username: string, @Query('password') password: string, - ): Promise { + ): Promise { this.logger.debug( `Trying to login partner with username ${username} using password ${password}`, ); try { - let xpath = `//partners/partner[username/text()='${username}' and password/text()='${password}']/*`; - let xmlStr = this.partnersService.getPartnersProperties(xpath); + const xpath = `//partners/partner[username/text()='${username}' and password/text()='${password}']/*`; + const xmlStr = this.partnersService.getPartnersProperties(xpath); // Check if account's data contains any information - If not, the login failed! if ( @@ -97,7 +97,7 @@ export class PartnersController { return xmlStr; } catch (err) { - let strErr = err.toString(); + const strErr = err.toString(); if (strErr.includes('Unterminated string literal')) { err = 'Error in XPath expression'; } @@ -123,14 +123,14 @@ export class PartnersController { @ApiOkResponse({ type: String, }) - async searchPartners(@Query('keyword') keyword: string): Promise { + async searchPartners(@Query('keyword') keyword: string): Promise { this.logger.debug(`Searching partner names by the keyword "${keyword}"`); try { - let xpath = `//partners/partner/name[contains(., '${keyword}')]`; + const xpath = `//partners/partner/name[contains(., '${keyword}')]`; return this.partnersService.getPartnersProperties(xpath); } catch (err) { - let strErr = err.toString(); + const strErr = err.toString(); if ( strErr.includes('XPath parse error') || strErr.includes('Unterminated string literal') diff --git a/src/partners/partners.service.ts b/src/partners/partners.service.ts index b4b84f1f..7c7025cb 100644 --- a/src/partners/partners.service.ts +++ b/src/partners/partners.service.ts @@ -1,7 +1,6 @@ import { Injectable, Logger } from '@nestjs/common'; - -const xpath = require('xpath'); -const dom = require('xmldom').DOMParser; +import { DOMParser } from 'xmldom'; +import xpath, { SelectReturnType } from 'xpath'; @Injectable() export class PartnersService { @@ -53,8 +52,8 @@ export class PartnersService { `; - private getPartnersXMLObj(): object { - let partnersXMLObj = new dom().parseFromString( + private getPartnersXMLObj(): Node { + const partnersXMLObj = new DOMParser().parseFromString( this.XML_AUTHORS_STR, 'text/xml', ); @@ -63,8 +62,8 @@ export class PartnersService { private selectPartnerPropertiesByXPATH( xpathExpression: string, - ): Array { - let partnersXMLObj = this.getPartnersXMLObj(); + ): SelectReturnType { + const partnersXMLObj = this.getPartnersXMLObj(); return xpath.select(xpathExpression, partnersXMLObj); } @@ -79,7 +78,7 @@ export class PartnersService { this.logger.debug( `xmlNodes's type wasn't 'Array', and it's value was: ${xmlNodes}`, ); - xmlNodes = Array(); + xmlNodes = []; } else { this.logger.debug(`Raw xpath xmlNodes value is: ${xmlNodes}`); } diff --git a/src/products/products.controller.ts b/src/products/products.controller.ts index 1a369e0d..624aa43a 100644 --- a/src/products/products.controller.ts +++ b/src/products/products.controller.ts @@ -1,7 +1,6 @@ import { Controller, Get, - Header, Logger, UseGuards, Headers, diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index 4d3944ce..ac615eaa 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -259,7 +259,6 @@ export class UsersController { async deleteUserPhotoById( @Param('id') id: number, @Query('isAdmin') isAdminParam: string, - @Res({ passthrough: true }) res: FastifyReply, ) { isAdminParam = isAdminParam.toLowerCase(); const isAdmin = diff --git a/src/users/users.service.ts b/src/users/users.service.ts index 62fbe581..748dbd99 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -23,7 +23,7 @@ export class UsersService { private readonly usersRepository: EntityRepository, ) {} - async createUser(user: UserDto, isBasicUser: boolean = true): Promise { + async createUser(user: UserDto, isBasicUser = true): Promise { this.log.debug(`Called createUser`); const u = new User(); diff --git a/src/utils/url.ts b/src/utils/url.ts index 57bbb9c1..70a17133 100644 --- a/src/utils/url.ts +++ b/src/utils/url.ts @@ -1,12 +1,12 @@ // Taken from PortSwigger's prototype pollution labs // VULNERABLE TO PROTOTYPE POLLUTION! -var splitUriIntoParamsPPVulnerable = (params, coerce = undefined) => { +const splitUriIntoParamsPPVulnerable = (params, coerce = undefined) => { if (params.charAt(0) === '?') { params = params.substring(1); } - var obj = {}, - coerce_types = { true: !0, false: !1, null: null }; + const obj = {}; + const coerce_types = { true: !0, false: !1, null: null }; if (!params) { return obj; @@ -16,13 +16,13 @@ var splitUriIntoParamsPPVulnerable = (params, coerce = undefined) => { .replace(/\+/g, ' ') .split('&') .forEach(function (v) { - var param = v.split('='), - key = decodeURIComponent(param[0]), - val, - cur = obj, - i = 0, - keys = key.split(']['), - keys_last = keys.length - 1; + const param = v.split('='); + let key = decodeURIComponent(param[0]); + let keys = key.split(']['); + let keys_last = keys.length - 1; + let val; + let cur: any = obj; + let i = 0; if (/\[/.test(keys[0]) && /\]$/.test(keys[keys_last])) { keys[keys_last] = keys[keys_last].replace(/\]$/, ''); @@ -48,12 +48,11 @@ var splitUriIntoParamsPPVulnerable = (params, coerce = undefined) => { if (keys_last) { for (; i <= keys_last; i++) { - //@ts-ignore key = keys[i] === '' ? cur.length : keys[i]; cur = cur[key] = i < keys_last - ? //@ts-ignore - cur[key] || (keys[i + 1] && isNaN(keys[i + 1]) ? {} : []) + ? cur[key] || + (keys[i + 1] && isNaN(keys[i + 1] as any) ? {} : []) : val; } } else {