From 8c2c659bee3feaa4cb8dbfd7be1e5ea7267b6dc1 Mon Sep 17 00:00:00 2001 From: Gijsdeman Date: Tue, 25 Feb 2025 14:21:00 +0100 Subject: [PATCH 1/9] chore: move eslint config --- eslint.config.mjs | 13 ++++ package.json | 1 + yarn.lock | 178 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 187 insertions(+), 5 deletions(-) create mode 100644 eslint.config.mjs diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..865f96e --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,13 @@ +import { eslintConfig as common } from '@gewis/eslint-config-typescript'; +import { eslintConfig as prettier } from '@gewis/prettier-config'; + +export default [ + ...common, + // TODO should move to eslint-config-typescript + { + rules: { + "import/no-named-as-default-member": "off" + } + }, + prettier +]; diff --git a/package.json b/package.json index 2cb3e80..ee5d9b2 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "validator": "^13.12.0" }, "devDependencies": { + "@gewis/eslint-config-typescript": "^2.2.3", "@gewis/prettier-config": "^2.2.2", "@types/axios": "^0.14.4", "@types/express": "5.0.0", diff --git a/yarn.lock b/yarn.lock index 284147f..b1d5de4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32,6 +32,18 @@ __metadata: languageName: node linkType: hard +"@eslint/compat@npm:^1.2.7": + version: 1.2.7 + resolution: "@eslint/compat@npm:1.2.7" + peerDependencies: + eslint: ^9.10.0 + peerDependenciesMeta: + eslint: + optional: true + checksum: 10c0/df89a0396750748c3748eb5fc582bd6cb89be6599d88ed1c5cc60ae0d13f77d4bf5fb30fabdb6c9ce16dda35745ef2e6417fa82548cde7d2b3fa5a896da02c8e + languageName: node + linkType: hard + "@eslint/eslintrc@npm:^2.1.4": version: 2.1.4 resolution: "@eslint/eslintrc@npm:2.1.4" @@ -49,6 +61,13 @@ __metadata: languageName: node linkType: hard +"@eslint/js@npm:*, @eslint/js@npm:9.21.0": + version: 9.21.0 + resolution: "@eslint/js@npm:9.21.0" + checksum: 10c0/86c24a2668808995037e3f40c758335df2ae277c553ac0cf84381a1a8698f3099d8a22dd9c388947e6b7f93fcc1142f62406072faaa2b83c43ca79993fc01bb3 + languageName: node + linkType: hard + "@eslint/js@npm:8.57.1": version: 8.57.1 resolution: "@eslint/js@npm:8.57.1" @@ -56,6 +75,22 @@ __metadata: languageName: node linkType: hard +"@gewis/eslint-config-typescript@npm:^2.2.3": + version: 2.2.3 + resolution: "@gewis/eslint-config-typescript@npm:2.2.3" + dependencies: + "@eslint/compat": "npm:^1.2.7" + "@eslint/js": "npm:9.21.0" + "@types/eslint__js": "npm:^9.14.0" + eslint-import-resolver-typescript: "npm:^3.8.3" + eslint-plugin-import: "npm:^2.31.0" + typescript-eslint: "npm:^8.25.0" + peerDependencies: + eslint: "*" + checksum: 10c0/28342353f0122cbf1ad54c3f85410310bf56d8a025b006e1b519ac4708c46c8a50b9f3ac761687d8dd852671b5c87f0aa0bfc2fb3c73dff19b19a0257e754eff + languageName: node + linkType: hard + "@gewis/prettier-config@npm:^2.2.2": version: 2.2.2 resolution: "@gewis/prettier-config@npm:2.2.2" @@ -581,6 +616,13 @@ __metadata: languageName: node linkType: hard +"@nolyfill/is-core-module@npm:1.0.39": + version: 1.0.39 + resolution: "@nolyfill/is-core-module@npm:1.0.39" + checksum: 10c0/34ab85fdc2e0250879518841f74a30c276bca4f6c3e13526d2d1fe515e1adf6d46c25fcd5989d22ea056d76f7c39210945180b4859fc83b050e2da411aa86289 + languageName: node + linkType: hard + "@npmcli/agent@npm:^3.0.0": version: 3.0.0 resolution: "@npmcli/agent@npm:3.0.0" @@ -789,6 +831,15 @@ __metadata: languageName: node linkType: hard +"@types/eslint__js@npm:^9.14.0": + version: 9.14.0 + resolution: "@types/eslint__js@npm:9.14.0" + dependencies: + "@eslint/js": "npm:*" + checksum: 10c0/da5e315aaf17a3e038eff3a4e1b90e360d9d22319653f43f746ad4b7f90dca2d1f8e0ea08f4d02b1b426e7baeb15610be4a30b64d28d16ef06d2feb75c549dc1 + languageName: node + linkType: hard + "@types/express-serve-static-core@npm:^5.0.0": version: 5.0.6 resolution: "@types/express-serve-static-core@npm:5.0.6" @@ -1081,7 +1132,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^8.25.0": +"@typescript-eslint/eslint-plugin@npm:8.25.0, @typescript-eslint/eslint-plugin@npm:^8.25.0": version: 8.25.0 resolution: "@typescript-eslint/eslint-plugin@npm:8.25.0" dependencies: @@ -1102,7 +1153,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/parser@npm:^8.25.0": +"@typescript-eslint/parser@npm:8.25.0, @typescript-eslint/parser@npm:^8.25.0": version: 8.25.0 resolution: "@typescript-eslint/parser@npm:8.25.0" dependencies: @@ -2023,7 +2074,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4, debug@npm:^4.1.1, debug@npm:^4.2.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.4.0": +"debug@npm:4, debug@npm:^4, debug@npm:^4.1.1, debug@npm:^4.2.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.7, debug@npm:^4.4.0": version: 4.4.0 resolution: "debug@npm:4.4.0" dependencies: @@ -2213,6 +2264,16 @@ __metadata: languageName: node linkType: hard +"enhanced-resolve@npm:^5.15.0": + version: 5.18.1 + resolution: "enhanced-resolve@npm:5.18.1" + dependencies: + graceful-fs: "npm:^4.2.4" + tapable: "npm:^2.2.0" + checksum: 10c0/4cffd9b125225184e2abed9fdf0ed3dbd2224c873b165d0838fd066cde32e0918626cba2f1f4bf6860762f13a7e2364fd89a82b99566be2873d813573ac71846 + languageName: node + linkType: hard + "env-paths@npm:^2.2.0": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -2384,6 +2445,30 @@ __metadata: languageName: node linkType: hard +"eslint-import-resolver-typescript@npm:^3.8.3": + version: 3.8.3 + resolution: "eslint-import-resolver-typescript@npm:3.8.3" + dependencies: + "@nolyfill/is-core-module": "npm:1.0.39" + debug: "npm:^4.3.7" + enhanced-resolve: "npm:^5.15.0" + get-tsconfig: "npm:^4.10.0" + is-bun-module: "npm:^1.0.2" + stable-hash: "npm:^0.0.4" + tinyglobby: "npm:^0.2.12" + peerDependencies: + eslint: "*" + eslint-plugin-import: "*" + eslint-plugin-import-x: "*" + peerDependenciesMeta: + eslint-plugin-import: + optional: true + eslint-plugin-import-x: + optional: true + checksum: 10c0/886ceeab4cad14958d7c7d3432ead2486374616c8ada7925ab96e55f919f2dbbbdbe7c3081d7d238231e84699849e82930417a66e05638bcc8202e1263edddeb + languageName: node + linkType: hard + "eslint-module-utils@npm:^2.12.0": version: 2.12.0 resolution: "eslint-module-utils@npm:2.12.0" @@ -2720,6 +2805,18 @@ __metadata: languageName: node linkType: hard +"fdir@npm:^6.4.3": + version: 6.4.3 + resolution: "fdir@npm:6.4.3" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 10c0/d13c10120e9625adf21d8d80481586200759928c19405a816b77dd28eaeb80e7c59c5def3e2941508045eb06d34eb47fad865ccc8bf98e6ab988bb0ed160fb6f + languageName: node + linkType: hard + "file-entry-cache@npm:^6.0.1": version: 6.0.1 resolution: "file-entry-cache@npm:6.0.1" @@ -2984,6 +3081,15 @@ __metadata: languageName: node linkType: hard +"get-tsconfig@npm:^4.10.0": + version: 4.10.0 + resolution: "get-tsconfig@npm:4.10.0" + dependencies: + resolve-pkg-maps: "npm:^1.0.0" + checksum: 10c0/c9b5572c5118923c491c04285c73bd55b19e214992af957c502a3be0fc0043bb421386ffd45ca3433c0a7fba81221ca300479e8393960acf15d0ed4563f38a86 + languageName: node + linkType: hard + "glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": version: 5.1.2 resolution: "glob-parent@npm:5.1.2" @@ -3083,7 +3189,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6": +"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 @@ -3407,6 +3513,15 @@ __metadata: languageName: node linkType: hard +"is-bun-module@npm:^1.0.2": + version: 1.3.0 + resolution: "is-bun-module@npm:1.3.0" + dependencies: + semver: "npm:^7.6.3" + checksum: 10c0/2966744188fcd28e0123c52158c7073973f88babfa9ab04e2846ec5862d6b0f8f398df6413429d930f7c5ee6111ce2cbfb3eb8652d9ec42d4a37dc5089a866fb + languageName: node + linkType: hard + "is-callable@npm:^1.2.7": version: 1.2.7 resolution: "is-callable@npm:1.2.7" @@ -4711,6 +4826,7 @@ __metadata: version: 0.0.0-use.local resolution: "parelpracht-server@workspace:." dependencies: + "@gewis/eslint-config-typescript": "npm:^2.2.3" "@gewis/prettier-config": "npm:^2.2.2" "@types/axios": "npm:^0.14.4" "@types/express": "npm:5.0.0" @@ -4998,6 +5114,13 @@ __metadata: languageName: node linkType: hard +"picomatch@npm:^4.0.2": + version: 4.0.2 + resolution: "picomatch@npm:4.0.2" + checksum: 10c0/7c51f3ad2bb42c776f49ebf964c644958158be30d0a510efd5a395e8d49cb5acfed5b82c0c5b365523ce18e6ab85013c9ebe574f60305892ec3fa8eee8304ccc + languageName: node + linkType: hard + "possible-typed-array-names@npm:^1.0.0": version: 1.1.0 resolution: "possible-typed-array-names@npm:1.1.0" @@ -5256,6 +5379,13 @@ __metadata: languageName: node linkType: hard +"resolve-pkg-maps@npm:^1.0.0": + version: 1.0.0 + resolution: "resolve-pkg-maps@npm:1.0.0" + checksum: 10c0/fb8f7bbe2ca281a73b7ef423a1cbc786fb244bd7a95cbe5c3fba25b27d327150beca8ba02f622baea65919a57e061eb5005204daa5f93ed590d9b77463a567ab + languageName: node + linkType: hard + "resolve@npm:^1.22.4": version: 1.22.10 resolution: "resolve@npm:1.22.10" @@ -5423,7 +5553,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": +"semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3": version: 7.7.1 resolution: "semver@npm:7.7.1" bin: @@ -5694,6 +5824,13 @@ __metadata: languageName: node linkType: hard +"stable-hash@npm:^0.0.4": + version: 0.0.4 + resolution: "stable-hash@npm:0.0.4" + checksum: 10c0/53d010d2a1b014fb60d398c095f43912c353b7b44774e55222bb26fd428bc75b73d7bdfcae509ce927c23ca9c5aff2dc1bc82f191d30e57a879550bc2952bdb0 + languageName: node + linkType: hard + "statuses@npm:2.0.1": version: 2.0.1 resolution: "statuses@npm:2.0.1" @@ -5921,6 +6058,13 @@ __metadata: languageName: node linkType: hard +"tapable@npm:^2.2.0": + version: 2.2.1 + resolution: "tapable@npm:2.2.1" + checksum: 10c0/bc40e6efe1e554d075469cedaba69a30eeb373552aaf41caeaaa45bf56ffacc2674261b106245bd566b35d8f3329b52d838e851ee0a852120acae26e622925c9 + languageName: node + linkType: hard + "tar@npm:^7.4.3": version: 7.4.3 resolution: "tar@npm:7.4.3" @@ -5979,6 +6123,16 @@ __metadata: languageName: node linkType: hard +"tinyglobby@npm:^0.2.12": + version: 0.2.12 + resolution: "tinyglobby@npm:0.2.12" + dependencies: + fdir: "npm:^6.4.3" + picomatch: "npm:^4.0.2" + checksum: 10c0/7c9be4fd3625630e262dcb19015302aad3b4ba7fc620f269313e688f2161ea8724d6cb4444baab5ef2826eb6bed72647b169a33ec8eea37501832a2526ff540f + languageName: node + linkType: hard + "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -6264,6 +6418,20 @@ __metadata: languageName: node linkType: hard +"typescript-eslint@npm:^8.25.0": + version: 8.25.0 + resolution: "typescript-eslint@npm:8.25.0" + dependencies: + "@typescript-eslint/eslint-plugin": "npm:8.25.0" + "@typescript-eslint/parser": "npm:8.25.0" + "@typescript-eslint/utils": "npm:8.25.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <5.8.0" + checksum: 10c0/bdc1165be1bc60311045ca69aa1bff4bbb7feac906c6b7885c4bc859693d8ca1b88840a1ba10b226ca2343c4bd7388b7a36e5c787b0d7f1bab5ababb80e783cc + languageName: node + linkType: hard + "typescript@npm:^5.7.2, typescript@npm:^5.7.3": version: 5.7.3 resolution: "typescript@npm:5.7.3" From 1b769bbe413326aa7668cde28f961347ccf734cd Mon Sep 17 00:00:00 2001 From: Gijsdeman Date: Tue, 25 Feb 2025 14:22:42 +0100 Subject: [PATCH 2/9] squash(eslint): initial fixes --- src/auth/LocalStrategy.ts | 2 +- src/controllers/CompanyController.ts | 4 +- src/controllers/ContactController.ts | 4 +- src/controllers/ContractController.ts | 4 +- src/controllers/InvoiceController.ts | 4 +- src/controllers/ProductCategoryController.ts | 4 +- src/controllers/ProductController.ts | 4 +- src/controllers/RoleController.ts | 2 +- src/controllers/RootController.ts | 2 +- src/controllers/UserController.ts | 4 +- src/controllers/VATController.ts | 4 +- src/database.ts | 2 +- src/dbvalidator/validate.ts | 2 +- src/entity/activity/CompanyActivity.ts | 2 +- src/entity/activity/ContractActivity.ts | 2 +- src/entity/activity/InvoiceActivity.ts | 2 +- src/entity/activity/ProductActivity.ts | 2 +- .../activity/ProductInstanceActivity.ts | 2 +- src/entity/file/CompanyFile.ts | 2 +- src/entity/file/ContractFile.ts | 2 +- src/entity/file/InvoiceFile.ts | 2 +- src/entity/file/ProductFile.ts | 2 +- src/helpers/activity.ts | 10 ++--- src/helpers/fileHelper.ts | 4 +- src/helpers/filters.ts | 2 +- src/helpers/rawQueries.ts | 2 +- src/helpers/validation.ts | 2 +- src/index.ts | 8 ++-- src/pdfgenerator/PdfGenerator.ts | 38 +++++++++---------- src/services/ActivityService.ts | 14 +++---- src/services/AuthService.ts | 2 +- src/services/CompanyService.ts | 2 +- src/services/ContractService.ts | 6 +-- src/services/FileService.ts | 18 ++++----- src/services/GDPRService.ts | 2 +- src/services/InvoiceService.ts | 6 +-- src/services/ProductInstanceService.ts | 6 +-- src/services/ProductService.ts | 2 +- src/services/ServerSettingsService.ts | 4 +- src/services/UserService.ts | 12 +++--- src/timedevents/cron.ts | 2 +- src/timedevents/events/tmpFolder.ts | 2 +- 42 files changed, 102 insertions(+), 102 deletions(-) diff --git a/src/auth/LocalStrategy.ts b/src/auth/LocalStrategy.ts index 04be098..e348564 100644 --- a/src/auth/LocalStrategy.ts +++ b/src/auth/LocalStrategy.ts @@ -1,5 +1,5 @@ -import { Strategy as LocalStrategy } from 'passport-local'; import crypto from 'crypto'; +import { Strategy as LocalStrategy } from 'passport-local'; import passport from 'passport'; import express from 'express'; import validator from 'validator'; diff --git a/src/controllers/CompanyController.ts b/src/controllers/CompanyController.ts index f9250e3..43e0bf7 100644 --- a/src/controllers/CompanyController.ts +++ b/src/controllers/CompanyController.ts @@ -1,4 +1,3 @@ -import { Body, Tags, Controller, Post, Route, Put, Get, Security, Response, Delete, Request } from 'tsoa'; import express from 'express'; import { body } from 'express-validator'; import { Company } from '../entity/Company'; @@ -11,7 +10,6 @@ import CompanyService, { CompanySummary, ETCompanyListResponse, } from '../services/CompanyService'; -import { ListParams } from './ListParams'; import ActivityService, { ActivityParams, FullActivityParams } from '../services/ActivityService'; import BaseActivity from '../entity/activity/BaseActivity'; import { CompanyActivity } from '../entity/activity/CompanyActivity'; @@ -26,6 +24,8 @@ import BaseFile from '../entity/file/BaseFile'; import { CompanyFile } from '../entity/file/CompanyFile'; import StatisticsService, { ContractedProductsAnalysis } from '../services/StatisticsService'; import { Roles } from '../entity/enums/Roles'; +import { ListParams } from './ListParams'; +import { Body, Tags, Controller, Post, Route, Put, Get, Security, Response, Delete, Request } from 'tsoa'; @Route('company') @Tags('Company') diff --git a/src/controllers/ContactController.ts b/src/controllers/ContactController.ts index 2d846e2..63c4b47 100644 --- a/src/controllers/ContactController.ts +++ b/src/controllers/ContactController.ts @@ -1,13 +1,13 @@ -import { Body, Controller, Post, Route, Put, Tags, Get, Security, Response, Request, Delete } from 'tsoa'; import { body } from 'express-validator'; import express from 'express'; import { Contact } from '../entity/Contact'; import { WrappedApiError } from '../helpers/error'; import ContactService, { ContactListResponse, ContactParams, ContactSummary } from '../services/ContactService'; -import { ListParams } from './ListParams'; import { validate } from '../helpers/validation'; import { Gender } from '../entity/enums/Gender'; import { ContactFunction } from '../entity/enums/ContactFunction'; +import { ListParams } from './ListParams'; +import { Body, Controller, Post, Route, Put, Tags, Get, Security, Response, Request, Delete } from 'tsoa'; @Route('contact') @Tags('Contact') diff --git a/src/controllers/ContractController.ts b/src/controllers/ContractController.ts index 5575577..e216171 100644 --- a/src/controllers/ContractController.ts +++ b/src/controllers/ContractController.ts @@ -1,9 +1,7 @@ -import { Body, Controller, Delete, Get, Post, Put, Request, Response, Route, Security, Tags } from 'tsoa'; import express from 'express'; import { body } from 'express-validator'; import { Contract } from '../entity/Contract'; import ContractService, { ContractListResponse, ContractParams } from '../services/ContractService'; -import { ListParams } from './ListParams'; import ProductInstanceService, { ProductInstanceParams } from '../services/ProductInstanceService'; import { ProductInstance } from '../entity/ProductInstance'; import { ApiError, HTTPStatus, WrappedApiError } from '../helpers/error'; @@ -31,6 +29,8 @@ import { Language } from '../entity/enums/Language'; import { RecentContract } from '../helpers/rawQueries'; import { ContractSummary } from '../entity/Summaries'; import { Roles } from '../entity/enums/Roles'; +import { ListParams } from './ListParams'; +import { Body, Controller, Delete, Get, Post, Put, Request, Response, Route, Security, Tags } from 'tsoa'; @Route('contract') @Tags('Contract') diff --git a/src/controllers/InvoiceController.ts b/src/controllers/InvoiceController.ts index c676cec..25708fc 100644 --- a/src/controllers/InvoiceController.ts +++ b/src/controllers/InvoiceController.ts @@ -1,10 +1,8 @@ -import { Body, Controller, Post, Route, Put, Tags, Get, Security, Response, Delete, Request } from 'tsoa'; import express from 'express'; import { body, ValidationChain } from 'express-validator'; import { Invoice } from '../entity/Invoice'; import { ApiError, HTTPStatus, WrappedApiError } from '../helpers/error'; import InvoiceService, { InvoiceCreateParams, InvoiceListResponse, InvoiceParams } from '../services/InvoiceService'; -import { ListParams } from './ListParams'; import ActivityService, { ActivityParams, FullActivityParams, InvoiceStatusParams } from '../services/ActivityService'; import BaseActivity from '../entity/activity/BaseActivity'; import { InvoiceActivity } from '../entity/activity/InvoiceActivity'; @@ -23,6 +21,8 @@ import { Language } from '../entity/enums/Language'; import { InvoiceStatus } from '../entity/enums/InvoiceStatus'; import { InvoiceSummary } from '../entity/Summaries'; import { Roles } from '../entity/enums/Roles'; +import { ListParams } from './ListParams'; +import { Body, Controller, Post, Route, Put, Tags, Get, Security, Response, Delete, Request } from 'tsoa'; @Route('invoice') @Tags('Invoice') diff --git a/src/controllers/ProductCategoryController.ts b/src/controllers/ProductCategoryController.ts index d2ec856..816945d 100644 --- a/src/controllers/ProductCategoryController.ts +++ b/src/controllers/ProductCategoryController.ts @@ -1,4 +1,3 @@ -import { Body, Controller, Delete, Get, Post, Put, Request, Response, Route, Security, Tags } from 'tsoa'; import express from 'express'; import { body } from 'express-validator'; import ProductCategoryService, { @@ -6,11 +5,12 @@ import ProductCategoryService, { CategoryParams, CategorySummary, } from '../services/ProductCategoryService'; -import { ListParams } from './ListParams'; import { WrappedApiError } from '../helpers/error'; import { ProductCategory } from '../entity/ProductCategory'; import { validate } from '../helpers/validation'; import StatisticsService, { ContractedProductsAnalysis } from '../services/StatisticsService'; +import { ListParams } from './ListParams'; +import { Body, Controller, Delete, Get, Post, Put, Request, Response, Route, Security, Tags } from 'tsoa'; @Route('category') @Tags('Product Category') diff --git a/src/controllers/ProductController.ts b/src/controllers/ProductController.ts index be15a91..78dbcc4 100644 --- a/src/controllers/ProductController.ts +++ b/src/controllers/ProductController.ts @@ -1,4 +1,3 @@ -import { Body, Controller, Post, Route, Put, Tags, Get, Request, Response, Security, Delete } from 'tsoa'; import express from 'express'; import { body } from 'express-validator'; import { Product } from '../entity/Product'; @@ -8,7 +7,6 @@ import ProductService, { ProductParams, ProductSummary, } from '../services/ProductService'; -import { ListParams, PaginationParams } from './ListParams'; import { validate, validateActivityParams, validateCommentParams, validateFileParams } from '../helpers/validation'; import { ApiError, HTTPStatus, WrappedApiError } from '../helpers/error'; import ActivityService, { ActivityParams, FullActivityParams } from '../services/ActivityService'; @@ -26,6 +24,8 @@ import ProductInstanceService, { ProductInstanceListResponse } from '../services import { AnalysisResultByYear } from '../helpers/rawQueries'; import { ProductPricing } from '../entity/ProductPricing'; import { Roles } from '../entity/enums/Roles'; +import { ListParams, PaginationParams } from './ListParams'; +import { Body, Controller, Post, Route, Put, Tags, Get, Request, Response, Security, Delete } from 'tsoa'; @Route('product') @Tags('Product') diff --git a/src/controllers/RoleController.ts b/src/controllers/RoleController.ts index b12ee85..4d2cb85 100644 --- a/src/controllers/RoleController.ts +++ b/src/controllers/RoleController.ts @@ -1,7 +1,7 @@ -import { Body, Controller, Get, Put, Response, Route, Security, Tags } from 'tsoa'; import { WrappedApiError } from '../helpers/error'; import { Role } from '../entity/Role'; import RoleService, { RoleParams } from '../services/RoleService'; +import { Body, Controller, Get, Put, Response, Route, Security, Tags } from 'tsoa'; @Route('role') @Tags('Role') diff --git a/src/controllers/RootController.ts b/src/controllers/RootController.ts index cc14021..dbac696 100644 --- a/src/controllers/RootController.ts +++ b/src/controllers/RootController.ts @@ -1,5 +1,4 @@ import express from 'express'; -import { Body, Controller, Get, Post, Query, Request, Response, Route, Security } from 'tsoa'; import { body } from 'express-validator'; import { WrappedApiError } from '../helpers/error'; import { validate } from '../helpers/validation'; @@ -7,6 +6,7 @@ import AuthService, { AuthStatus, Profile } from '../services/AuthService'; import ServerSettingsService, { SetupParams } from '../services/ServerSettingsService'; import StatisticsService from '../services/StatisticsService'; import { ldapEnabled, LoginMethods } from '../auth'; +import { Body, Controller, Get, Post, Query, Request, Response, Route, Security } from 'tsoa'; export interface ResetPasswordRequest { password: string; diff --git a/src/controllers/UserController.ts b/src/controllers/UserController.ts index bab795e..ff0490e 100644 --- a/src/controllers/UserController.ts +++ b/src/controllers/UserController.ts @@ -1,10 +1,8 @@ -import { Body, Controller, Delete, Get, Post, Put, Request, Response, Route, Security, Tags } from 'tsoa'; import express from 'express'; import { body } from 'express-validator'; import { User } from '../entity/User'; import { ApiError, HTTPStatus, WrappedApiError } from '../helpers/error'; import UserService, { TransferUserParams, UserListResponse, UserParams, UserSummary } from '../services/UserService'; -import { ListParams } from './ListParams'; import { validate } from '../helpers/validation'; import { Gender } from '../entity/enums/Gender'; import { Roles } from '../entity/enums/Roles'; @@ -13,6 +11,8 @@ import { IdentityLocal } from '../entity/IdentityLocal'; import AuthService, { LdapIdentityParams } from '../services/AuthService'; import { IdentityLDAP } from '../entity/IdentityLDAP'; import GDPRService from '../services/GDPRService'; +import { ListParams } from './ListParams'; +import { Body, Controller, Delete, Get, Post, Put, Request, Response, Route, Security, Tags } from 'tsoa'; @Route('user') @Tags('User') diff --git a/src/controllers/VATController.ts b/src/controllers/VATController.ts index b8c2c66..75bf33e 100644 --- a/src/controllers/VATController.ts +++ b/src/controllers/VATController.ts @@ -1,11 +1,11 @@ -import { Body, Controller, Get, Post, Put, Request, Response, Route, Security, Tags } from 'tsoa'; import express from 'express'; import { body } from 'express-validator'; import VATService, { VATListResponse, VATParams, VATSummary } from '../services/VATService'; -import { ListParams } from './ListParams'; import { WrappedApiError } from '../helpers/error'; import { ValueAddedTax } from '../entity/ValueAddedTax'; import { validate } from '../helpers/validation'; +import { ListParams } from './ListParams'; +import { Body, Controller, Get, Post, Put, Request, Response, Route, Security, Tags } from 'tsoa'; @Route('VAT') @Tags('Value Added Tax') diff --git a/src/database.ts b/src/database.ts index 954eef5..8d312b7 100644 --- a/src/database.ts +++ b/src/database.ts @@ -1,5 +1,5 @@ -import { DataSource } from 'typeorm'; import fs from 'fs'; +import { DataSource } from 'typeorm'; import { Company } from './entity/Company'; import { Contact } from './entity/Contact'; import { Contract } from './entity/Contract'; diff --git a/src/dbvalidator/validate.ts b/src/dbvalidator/validate.ts index 5b3fd9b..efc668c 100644 --- a/src/dbvalidator/validate.ts +++ b/src/dbvalidator/validate.ts @@ -1,4 +1,5 @@ import dotenv from 'dotenv'; +import AppDataSource from '../database'; import { allContractsAreCreated, allProductsAreCancelledIfContractIsCancelled, @@ -7,7 +8,6 @@ import { import { allInvoicesAreCreated } from './invoices'; import { allProductInstancesWereNotDelivered } from './productInstances'; import { replaceGEWISRecipient } from './GEWISrecipient'; -import AppDataSource from '../database'; dotenv.config({ path: '.env' }); diff --git a/src/entity/activity/CompanyActivity.ts b/src/entity/activity/CompanyActivity.ts index 26c07b0..1b27d09 100644 --- a/src/entity/activity/CompanyActivity.ts +++ b/src/entity/activity/CompanyActivity.ts @@ -1,9 +1,9 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; // eslint-disable-next-line import/no-cycle -import BaseActivity from './BaseActivity'; // eslint-disable-next-line import/no-cycle import { Company } from '../Company'; import { BaseEnt } from '../BaseEnt'; +import BaseActivity from './BaseActivity'; @Entity() export class CompanyActivity extends BaseActivity { diff --git a/src/entity/activity/ContractActivity.ts b/src/entity/activity/ContractActivity.ts index cbc9491..d414dab 100644 --- a/src/entity/activity/ContractActivity.ts +++ b/src/entity/activity/ContractActivity.ts @@ -1,11 +1,11 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; // eslint-disable-next-line import/no-cycle -import BaseActivity from './BaseActivity'; // eslint-disable-next-line import/no-cycle import { Contract } from '../Contract'; import { ContractStatus } from '../enums/ContractStatus'; import { BaseEnt } from '../BaseEnt'; import { ApiError, HTTPStatus } from '../../helpers/error'; +import BaseActivity from './BaseActivity'; @Entity() export class ContractActivity extends BaseActivity { diff --git a/src/entity/activity/InvoiceActivity.ts b/src/entity/activity/InvoiceActivity.ts index b5814e3..678144c 100644 --- a/src/entity/activity/InvoiceActivity.ts +++ b/src/entity/activity/InvoiceActivity.ts @@ -1,11 +1,11 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; // eslint-disable-next-line import/no-cycle -import BaseActivity from './BaseActivity'; // eslint-disable-next-line import/no-cycle import { Invoice } from '../Invoice'; import { InvoiceStatus } from '../enums/InvoiceStatus'; import { BaseEnt } from '../BaseEnt'; import { ApiError, HTTPStatus } from '../../helpers/error'; +import BaseActivity from './BaseActivity'; @Entity() export class InvoiceActivity extends BaseActivity { diff --git a/src/entity/activity/ProductActivity.ts b/src/entity/activity/ProductActivity.ts index 73dbe82..0ca952e 100644 --- a/src/entity/activity/ProductActivity.ts +++ b/src/entity/activity/ProductActivity.ts @@ -1,9 +1,9 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; // eslint-disable-next-line import/no-cycle -import BaseActivity from './BaseActivity'; // eslint-disable-next-line import/no-cycle import { Product } from '../Product'; import { BaseEnt } from '../BaseEnt'; +import BaseActivity from './BaseActivity'; @Entity() export class ProductActivity extends BaseActivity { diff --git a/src/entity/activity/ProductInstanceActivity.ts b/src/entity/activity/ProductInstanceActivity.ts index 9a3c1f0..1c2398f 100644 --- a/src/entity/activity/ProductInstanceActivity.ts +++ b/src/entity/activity/ProductInstanceActivity.ts @@ -1,11 +1,11 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; // eslint-disable-next-line import/no-cycle -import BaseActivity from './BaseActivity'; // eslint-disable-next-line import/no-cycle import { ProductInstance } from '../ProductInstance'; import { ProductInstanceStatus } from '../enums/ProductActivityStatus'; import { BaseEnt } from '../BaseEnt'; import { ApiError, HTTPStatus } from '../../helpers/error'; +import BaseActivity from './BaseActivity'; @Entity() export class ProductInstanceActivity extends BaseActivity { diff --git a/src/entity/file/CompanyFile.ts b/src/entity/file/CompanyFile.ts index aa1b8c6..834d2ac 100644 --- a/src/entity/file/CompanyFile.ts +++ b/src/entity/file/CompanyFile.ts @@ -1,7 +1,7 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; +import { Company } from '../Company'; import BaseFile from './BaseFile'; // eslint-disable-next-line import/no-cycle -import { Company } from '../Company'; @Entity() export class CompanyFile extends BaseFile { diff --git a/src/entity/file/ContractFile.ts b/src/entity/file/ContractFile.ts index 5ed82db..8ea7c29 100644 --- a/src/entity/file/ContractFile.ts +++ b/src/entity/file/ContractFile.ts @@ -1,7 +1,7 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; +import { Contract } from '../Contract'; import BaseFile from './BaseFile'; // eslint-disable-next-line import/no-cycle -import { Contract } from '../Contract'; @Entity() export class ContractFile extends BaseFile { diff --git a/src/entity/file/InvoiceFile.ts b/src/entity/file/InvoiceFile.ts index bbbae59..27b81e9 100644 --- a/src/entity/file/InvoiceFile.ts +++ b/src/entity/file/InvoiceFile.ts @@ -1,7 +1,7 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; +import { Invoice } from '../Invoice'; import BaseFile from './BaseFile'; // eslint-disable-next-line import/no-cycle -import { Invoice } from '../Invoice'; @Entity() export class InvoiceFile extends BaseFile { diff --git a/src/entity/file/ProductFile.ts b/src/entity/file/ProductFile.ts index 5982504..432550f 100644 --- a/src/entity/file/ProductFile.ts +++ b/src/entity/file/ProductFile.ts @@ -1,7 +1,7 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; +import { Product } from '../Product'; import BaseFile from './BaseFile'; // eslint-disable-next-line import/no-cycle -import { Product } from '../Product'; @Entity() export class ProductFile extends BaseFile { diff --git a/src/helpers/activity.ts b/src/helpers/activity.ts index 3b8185a..9517c67 100644 --- a/src/helpers/activity.ts +++ b/src/helpers/activity.ts @@ -9,12 +9,12 @@ import { Product } from '../entity/Product'; import { Company } from '../entity/Company'; import { Contact } from '../entity/Contact'; import { ProductCategory } from '../entity/ProductCategory'; -import Currency from './currency'; -import { timeToYearDayTime } from './timestamp'; -import getEntityChanges from './entityChanges'; import { Language } from '../entity/enums/Language'; import BaseActivity from '../entity/activity/BaseActivity'; import AppDataSource from '../database'; +import Currency from './currency'; +import { timeToYearDayTime } from './timestamp'; +import getEntityChanges from './entityChanges'; /** * Convert an array of strings to a single string, where all items are split by @@ -301,7 +301,7 @@ export async function createActivitiesForEntityEdits( descriptionDutch: createReassignActivityDescription( // @ts-ignore As checked in the if-statement above, the "changes" variable does have // an assignedToId value - await new UserService().getUser(changes.assignedToId!), + await new UserService().getUser(changes.assignedToId), // @ts-ignore Therefore, the real entity must also have this property by definition await new UserService().getUser(entity.assignedToId), Language.DUTCH, @@ -309,7 +309,7 @@ export async function createActivitiesForEntityEdits( descriptionEnglish: createReassignActivityDescription( // @ts-ignore As checked in the if-statement above, the "changes" variable does have // an assignedToId value - await new UserService().getUser(changes.assignedToId!), + await new UserService().getUser(changes.assignedToId), // @ts-ignore Therefore, the real entity must also have this property by definition await new UserService().getUser(entity.assignedToId), Language.ENGLISH, diff --git a/src/helpers/fileHelper.ts b/src/helpers/fileHelper.ts index a33be1b..b6b6f00 100644 --- a/src/helpers/fileHelper.ts +++ b/src/helpers/fileHelper.ts @@ -1,8 +1,8 @@ -import { Controller } from 'tsoa'; import * as fs from 'fs'; -import mime from 'mime'; import path from 'path'; +import mime from 'mime'; import BaseFile from '../entity/file/BaseFile'; +import { Controller } from 'tsoa'; export const workDirLoc = 'tmp/'; export const generateDirLoc = 'data/generated/'; diff --git a/src/helpers/filters.ts b/src/helpers/filters.ts index a358d4e..a1bbb62 100644 --- a/src/helpers/filters.ts +++ b/src/helpers/filters.ts @@ -41,7 +41,7 @@ export function addQuerySearch(fieldNames: string[], search?: temp[intermediates[intermediates.length - 1]] = ILike(`%${searchTerm}%`); // All other intermediates are entities, so we create a nested object over them for (let i = intermediates.length - 2; i >= 0; i--) { - let temp2: any = {}; + const temp2: any = {}; temp2[intermediates[i]] = temp; temp = temp2; } diff --git a/src/helpers/rawQueries.ts b/src/helpers/rawQueries.ts index f8bb1d1..b05cc23 100644 --- a/src/helpers/rawQueries.ts +++ b/src/helpers/rawQueries.ts @@ -4,10 +4,10 @@ import { ContractStatus } from '../entity/enums/ContractStatus'; import { InvoiceStatus } from '../entity/enums/InvoiceStatus'; import { ContractSummary, InvoiceSummary } from '../entity/Summaries'; import { ProductInstanceStatus } from '../entity/enums/ProductActivityStatus'; +import AppDataSource from '../database'; import { currentFinancialYear } from './timestamp'; import { ApiError, HTTPStatus } from './error'; import replaceAll from './replaceAll'; -import AppDataSource from '../database'; export interface ETCompany { id: number; diff --git a/src/helpers/validation.ts b/src/helpers/validation.ts index 7c7c2d0..93b9628 100644 --- a/src/helpers/validation.ts +++ b/src/helpers/validation.ts @@ -1,7 +1,7 @@ import express from 'express'; import { body, ValidationChain, validationResult } from 'express-validator'; -import { ApiError, HTTPStatus } from './error'; import ContactService from '../services/ContactService'; +import { ApiError, HTTPStatus } from './error'; /** * Run a list of validations (in parallel) on a request object diff --git a/src/index.ts b/src/index.ts index 9251b32..dcec251 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,21 +1,19 @@ import 'reflect-metadata'; import * as fs from 'fs'; +import path from 'path'; import express, { Express } from 'express'; import dotenv from 'dotenv'; -dotenv.config({ path: '.env' }); - import errorhandler from 'strong-error-handler'; import swaggerUi from 'swagger-ui-express'; -import path from 'path'; import methodOverride from 'method-override'; import bodyParser from 'body-parser'; import session from 'express-session'; import { TypeormStore } from 'connect-typeorm'; import passport from 'passport'; -import startEvents from './timedevents/cron'; import swaggerDocument from '../build/swagger.json'; import { RegisterRoutes } from '../build/routes'; +import startEvents from './timedevents/cron'; import './controllers/RootController'; import './controllers/ProductCategoryController'; import './controllers/ProductController'; @@ -33,6 +31,8 @@ import { ldapLogin, LDAPStrategy } from './auth'; import AppDataSource from './database'; import { DataSource } from 'typeorm'; +dotenv.config({ path: '.env' }); + const PORT = process.env.PORT || 3001; export function setupSessionSupport(dataSource: DataSource, app: Express) { diff --git a/src/pdfgenerator/PdfGenerator.ts b/src/pdfgenerator/PdfGenerator.ts index 08af7c4..f5820ba 100644 --- a/src/pdfgenerator/PdfGenerator.ts +++ b/src/pdfgenerator/PdfGenerator.ts @@ -4,13 +4,6 @@ import latex from 'node-latex'; import { v4 as uuidv4 } from 'uuid'; import { Contract } from '../entity/Contract'; import { Invoice } from '../entity/Invoice'; -import { - ContractGenSettings, - ContractType, - CustomInvoiceGenSettings, - InvoiceGenSettings, - ReturnFileType, -} from './GenSettings'; import { ApiError, HTTPStatus } from '../helpers/error'; import { Company } from '../entity/Company'; import { Contact } from '../entity/Contact'; @@ -25,6 +18,13 @@ import countries from '../helpers/countries.json'; import { VAT } from '../entity/enums/ValueAddedTax'; import { ValueAddedTax } from '../entity/ValueAddedTax'; import AppDataSource from '../database'; +import { + ContractGenSettings, + ContractType, + CustomInvoiceGenSettings, + InvoiceGenSettings, + ReturnFileType, +} from './GenSettings'; const contractDutch = 'template_contract.tex'; const contractEnglish = 'template_contract_engels.tex'; @@ -177,7 +177,7 @@ export default class PdfGenerator { if (useInvoiceAddress) { const companyCountry = company.invoiceAddressCountry - ? countries.find((country) => country.Code === company.invoiceAddressCountry!.toUpperCase()) + ? countries.find((country) => country.Code === company.invoiceAddressCountry.toUpperCase()) : undefined; template = replaceAll(template, '{{street}}', company.invoiceAddressStreet); template = replaceAll(template, '{{postalcode}}', company.invoiceAddressPostalCode); @@ -188,7 +188,7 @@ export default class PdfGenerator { companyCountry !== undefined ? companyCountry.Name : company.invoiceAddressCountry, ); } else { - const companyCountry = countries.find((country) => country.Code === company.addressCountry!.toUpperCase()); + const companyCountry = countries.find((country) => country.Code === company.addressCountry.toUpperCase()); template = replaceAll(template, '{{street}}', company.addressStreet); template = replaceAll(template, '{{postalcode}}', company.addressPostalCode); template = replaceAll(template, '{{city}}', company.addressCity); @@ -202,7 +202,7 @@ export default class PdfGenerator { template = replaceAll(template, '{{ourreference}}', ourReference); template = this.replaceAllSafe(template, '{{yourreference}}', theirReference); - let dueDate = new Date(date); + const dueDate = new Date(date); dueDate.setDate(date.getDate() + 30); template = replaceAll(template, '{{dueday}}', dueDate.getDate().toString()); template = replaceAll(template, '{{duemonth}}', (dueDate.getMonth() + 1).toString()); @@ -433,11 +433,11 @@ export default class PdfGenerator { useInvoiceAddress, '', `F${invoice.id}`, - !!invoice.poNumber ? invoice.poNumber : undefined, + invoice.poNumber ? invoice.poNumber : undefined, ); // Setting invoice specific information - let dueDate = new Date(invoice.startDate); + const dueDate = new Date(invoice.startDate); dueDate.setDate(invoice.startDate.getDate() + 30); file = replaceAll(file, '{{dueday}}', dueDate.getDate().toString()); file = replaceAll(file, '{{duemonth}}', (dueDate.getMonth() + 1).toString()); @@ -445,8 +445,8 @@ export default class PdfGenerator { file = replaceAll(file, '{{debtornumber}}', `C${settings.recipient.id}`); - let startDate = new Date(invoice.startDate); - let quartiles = { + const startDate = new Date(invoice.startDate); + const quartiles = { Q1: [new Date(invoice.startDate.getFullYear(), 6, 1), new Date(invoice.startDate.getFullYear(), 8, 30)], Q2: [new Date(invoice.startDate.getFullYear(), 9, 1), new Date(invoice.startDate.getFullYear(), 11, 31)], Q3: [new Date(invoice.startDate.getFullYear(), 0, 1), new Date(invoice.startDate.getFullYear(), 2, 31)], @@ -486,14 +486,14 @@ export default class PdfGenerator { let file = fs.readFileSync(path.join(this.templateDir, invoicePath)).toString(); - let customCompany = new Company(); + const customCompany = new Company(); customCompany.name = params.recipient.organizationName ? params.recipient.organizationName : params.recipient.name; customCompany.invoiceAddressStreet = params.recipient.street ?? ''; customCompany.invoiceAddressPostalCode = params.recipient.postalCode ?? ''; customCompany.invoiceAddressCity = params.recipient.city ?? ''; customCompany.invoiceAddressCountry = params.recipient.country ?? ''; - let customRecipient = new Contact(); + const customRecipient = new Contact(); customRecipient.firstName = params.recipient.organizationName ? params.recipient.name : ''; customRecipient.lastNamePreposition = ''; customRecipient.lastName = ''; @@ -508,11 +508,11 @@ export default class PdfGenerator { true, params.subject, params.ourReference, - !!params.theirReference ? params.theirReference : undefined, + params.theirReference ? params.theirReference : undefined, ); // Setting invoice specific information - let dueDate = new Date(params.date); + const dueDate = new Date(params.date); dueDate.setDate(params.date.getDate() + 30); file = replaceAll(file, '{{dueday}}', dueDate.getDate().toString()); file = replaceAll(file, '{{duemonth}}', (dueDate.getMonth() + 1).toString()); @@ -531,7 +531,7 @@ export default class PdfGenerator { let customProduct; for (let i = 0; i < params.products.length; i++) { customProduct = params.products[i]; - let basePrice = customProduct.pricePerOne * customProduct.amount; + const basePrice = customProduct.pricePerOne * customProduct.amount; const valueAddedTax = await repo.findOne({ where: { diff --git a/src/services/ActivityService.ts b/src/services/ActivityService.ts index 6445a86..be960ce 100644 --- a/src/services/ActivityService.ts +++ b/src/services/ActivityService.ts @@ -6,9 +6,7 @@ import { ProductInstanceActivity } from '../entity/activity/ProductInstanceActiv import { ApiError, HTTPStatus } from '../helpers/error'; import { User } from '../entity/User'; // eslint-disable-next-line import/no-cycle -import ProductInstanceService from './ProductInstanceService'; // eslint-disable-next-line import/no-cycle -import ContractService from './ContractService'; import { Contract } from '../entity/Contract'; import { ActivityType } from '../entity/enums/ActivityType'; import { ContractStatus } from '../entity/enums/ContractStatus'; @@ -20,6 +18,8 @@ import { appendProductActivityDescription, createAddProductActivityDescription } import { Language } from '../entity/enums/Language'; import AppDataSource from '../database'; import { Roles } from '../entity/enums/Roles'; +import ContractService from './ContractService'; +import ProductInstanceService from './ProductInstanceService'; export interface ActivityParams { description: string; @@ -73,7 +73,7 @@ export default class ActivityService { if (activity?.getRelatedEntityId() !== entityId) throw new ApiError(HTTPStatus.BadRequest, 'Activity does not belong to the related entity'); - return activity!; + return activity; } async getActivity(id: number, relations: string[] = []): Promise { @@ -417,14 +417,14 @@ export default class ActivityService { let activity = (await this.repo.findOneBy({ id: activityId })) as T; if (activity == null) throw new ApiError(HTTPStatus.NotFound); activity = this.validateActivity(activity, entityId); - let p = { + const p = { descriptionDutch: params.descriptionDutch, descriptionEnglish: params.descriptionEnglish, }; - await this.repo.update(activity!.id, p); + await this.repo.update(activity.id, p); activity = (await this.repo.findOneBy({ id: activityId })) as T; - return activity! as T; + return activity; } /** @@ -457,6 +457,6 @@ export default class ActivityService { throw new ApiError(HTTPStatus.BadRequest, 'Cannot delete the initial (created) status of an entity'); } - await this.repo.delete(activity!.id); + await this.repo.delete(activity.id); } } diff --git a/src/services/AuthService.ts b/src/services/AuthService.ts index 8e66e0d..c3284ac 100644 --- a/src/services/AuthService.ts +++ b/src/services/AuthService.ts @@ -133,7 +133,7 @@ export default class AuthService { ); } - return identity!; + return identity; } async updateIdentityLdap(user: User, params: Partial): Promise { diff --git a/src/services/CompanyService.ts b/src/services/CompanyService.ts index 82eb51e..b05d81f 100644 --- a/src/services/CompanyService.ts +++ b/src/services/CompanyService.ts @@ -9,9 +9,9 @@ import FileHelper from '../helpers/fileHelper'; import { createActivitiesForEntityEdits } from '../helpers/activity'; import { CompanyActivity } from '../entity/activity/CompanyActivity'; import { User } from '../entity/User'; -import ActivityService from './ActivityService'; import RawQueries, { ETCompany } from '../helpers/rawQueries'; import AppDataSource from '../database'; +import ActivityService from './ActivityService'; // May not be correct yet export interface CompanyParams { diff --git a/src/services/ContractService.ts b/src/services/ContractService.ts index 4063ef1..b6d3221 100644 --- a/src/services/ContractService.ts +++ b/src/services/ContractService.ts @@ -4,9 +4,6 @@ import { Contract } from '../entity/Contract'; import { User } from '../entity/User'; import { ApiError, HTTPStatus } from '../helpers/error'; import { ContractActivity } from '../entity/activity/ContractActivity'; -import ActivityService, { FullActivityParams } from './ActivityService'; -import ContactService from './ContactService'; -import CompanyService from './CompanyService'; import { ContactFunction } from '../entity/enums/ContactFunction'; import { CompanyStatus } from '../entity/enums/CompanyStatus'; import { ActivityType } from '../entity/enums/ActivityType'; @@ -17,6 +14,9 @@ import { Roles } from '../entity/enums/Roles'; import { ContractSummary } from '../entity/Summaries'; import { createActivitiesForEntityEdits } from '../helpers/activity'; import AppDataSource from '../database'; +import CompanyService from './CompanyService'; +import ContactService from './ContactService'; +import ActivityService, { FullActivityParams } from './ActivityService'; export interface ContractParams { title: string; diff --git a/src/services/FileService.ts b/src/services/FileService.ts index be69dbb..af40c47 100644 --- a/src/services/FileService.ts +++ b/src/services/FileService.ts @@ -1,12 +1,11 @@ -import { Repository } from 'typeorm'; import * as fs from 'fs'; -import express from 'express'; -import multer from 'multer'; -import { v4 as uuidv4 } from 'uuid'; import path from 'path'; +import { v4 as uuidv4 } from 'uuid'; +import multer from 'multer'; +import express from 'express'; +import { Repository } from 'typeorm'; import mime from 'mime'; import BaseFile from '../entity/file/BaseFile'; -import UserService from './UserService'; import { ContractFile } from '../entity/file/ContractFile'; import { InvoiceFile } from '../entity/file/InvoiceFile'; import { ApiError, HTTPStatus } from '../helpers/error'; @@ -18,8 +17,6 @@ import { ReturnFileType, } from '../pdfgenerator/GenSettings'; import PdfGenerator from '../pdfgenerator/PdfGenerator'; -import InvoiceService from './InvoiceService'; -import ContractService from './ContractService'; import FileHelper, { uploadCompanyLogoDirLoc, uploadDirLoc, @@ -27,13 +24,16 @@ import FileHelper, { uploadUserBackgroundDirLoc, } from '../helpers/fileHelper'; import { ProductFile } from '../entity/file/ProductFile'; -import ContactService from './ContactService'; import { User } from '../entity/User'; import { validateFileParams } from '../helpers/validation'; import { CompanyFile } from '../entity/file/CompanyFile'; import { Language } from '../entity/enums/Language'; -import CompanyService from './CompanyService'; import AppDataSource from '../database'; +import CompanyService from './CompanyService'; +import ContactService from './ContactService'; +import ContractService from './ContractService'; +import InvoiceService from './InvoiceService'; +import UserService from './UserService'; export interface FileParams { name?: string; diff --git a/src/services/GDPRService.ts b/src/services/GDPRService.ts index f22ead4..939b025 100644 --- a/src/services/GDPRService.ts +++ b/src/services/GDPRService.ts @@ -11,13 +11,13 @@ import { Product } from '../entity/Product'; import { ProductInstanceActivity } from '../entity/activity/ProductInstanceActivity'; import { Invoice } from '../entity/Invoice'; import { ProductActivity } from '../entity/activity/ProductActivity'; -import UserService from './UserService'; import { InvoiceActivity } from '../entity/activity/InvoiceActivity'; import { CompanyFile } from '../entity/file/CompanyFile'; import { ContractFile } from '../entity/file/ContractFile'; import { InvoiceFile } from '../entity/file/InvoiceFile'; import { ProductFile } from '../entity/file/ProductFile'; import { ProductInstance } from '../entity/ProductInstance'; +import UserService from './UserService'; export type ActivitiesGDPRResponse = Pick< BaseActivity, diff --git a/src/services/InvoiceService.ts b/src/services/InvoiceService.ts index 3ae61d4..bca9f3f 100644 --- a/src/services/InvoiceService.ts +++ b/src/services/InvoiceService.ts @@ -5,18 +5,18 @@ import { ProductInstance } from '../entity/ProductInstance'; import { User } from '../entity/User'; import { ApiError, HTTPStatus } from '../helpers/error'; import { addQueryBuilderFilters, addQueryBuilderSearch } from '../helpers/filters'; -import ProductInstanceService from './ProductInstanceService'; -import ActivityService, { FullActivityParams } from './ActivityService'; import RawQueries, { ExpiredInvoice } from '../helpers/rawQueries'; import { InvoiceActivity } from '../entity/activity/InvoiceActivity'; import { ActivityType } from '../entity/enums/ActivityType'; import { InvoiceStatus } from '../entity/enums/InvoiceStatus'; -import ServerSettingsService from './ServerSettingsService'; import { ServerSetting } from '../entity/ServerSetting'; import { InvoiceSummary } from '../entity/Summaries'; import { createActivitiesForEntityEdits } from '../helpers/activity'; import getEntityChanges from '../helpers/entityChanges'; import AppDataSource from '../database'; +import ServerSettingsService from './ServerSettingsService'; +import ActivityService, { FullActivityParams } from './ActivityService'; +import ProductInstanceService from './ProductInstanceService'; export interface InvoiceParams { title: string; diff --git a/src/services/ProductInstanceService.ts b/src/services/ProductInstanceService.ts index af2c62d..4489617 100644 --- a/src/services/ProductInstanceService.ts +++ b/src/services/ProductInstanceService.ts @@ -2,14 +2,11 @@ import { FindManyOptions, IsNull, Not, Repository } from 'typeorm'; import { ProductInstance } from '../entity/ProductInstance'; import { ApiError, HTTPStatus } from '../helpers/error'; // eslint-disable-next-line import/no-cycle -import InvoiceService from './InvoiceService'; // eslint-disable-next-line import/no-cycle -import ActivityService, { FullActivityParams } from './ActivityService'; import { ProductInstanceActivity } from '../entity/activity/ProductInstanceActivity'; import { User } from '../entity/User'; import { ContractActivity } from '../entity/activity/ContractActivity'; import { InvoiceActivity } from '../entity/activity/InvoiceActivity'; -import ProductService from './ProductService'; import { ProductStatus } from '../entity/enums/ProductStatus'; import { ContractStatus } from '../entity/enums/ContractStatus'; import { ActivityType } from '../entity/enums/ActivityType'; @@ -18,6 +15,9 @@ import { InvoiceStatus } from '../entity/enums/InvoiceStatus'; import { createActivitiesForEntityEdits, createDelProductActivityDescription } from '../helpers/activity'; import { Language } from '../entity/enums/Language'; import AppDataSource from '../database'; +import ProductService from './ProductService'; +import ActivityService, { FullActivityParams } from './ActivityService'; +import InvoiceService from './InvoiceService'; export interface ProductInstanceParams { productId: number; diff --git a/src/services/ProductService.ts b/src/services/ProductService.ts index 7fb7f78..80fb0e8 100644 --- a/src/services/ProductService.ts +++ b/src/services/ProductService.ts @@ -7,9 +7,9 @@ import { addQueryWhereClause } from '../helpers/filters'; import { User } from '../entity/User'; import { createActivitiesForEntityEdits } from '../helpers/activity'; import { ProductActivity } from '../entity/activity/ProductActivity'; -import ActivityService from './ActivityService'; import { ProductPricing } from '../entity/ProductPricing'; import AppDataSource from '../database'; +import ActivityService from './ActivityService'; export interface ProductParams { nameDutch: string; diff --git a/src/services/ServerSettingsService.ts b/src/services/ServerSettingsService.ts index 7c392cf..8caa325 100644 --- a/src/services/ServerSettingsService.ts +++ b/src/services/ServerSettingsService.ts @@ -1,11 +1,11 @@ import { Repository } from 'typeorm'; import { ServerSetting } from '../entity/ServerSetting'; import { ApiError, HTTPStatus } from '../helpers/error'; -import AuthService from './AuthService'; -import UserService, { UserParams } from './UserService'; import { ldapEnabled } from '../auth'; import AppDataSource from '../database'; import { User } from '../entity/User'; +import UserService, { UserParams } from './UserService'; +import AuthService from './AuthService'; export interface SetupParams { admin: UserParams; diff --git a/src/services/UserService.ts b/src/services/UserService.ts index d652989..392cc1a 100644 --- a/src/services/UserService.ts +++ b/src/services/UserService.ts @@ -1,5 +1,6 @@ -import { FindManyOptions, Repository } from 'typeorm'; import path from 'path'; +import { FindManyOptions, Repository } from 'typeorm'; +import validator from 'validator'; import { ListParams } from '../controllers/ListParams'; import { Gender } from '../entity/enums/Gender'; import { IdentityLocal } from '../entity/IdentityLocal'; @@ -7,17 +8,16 @@ import { Role } from '../entity/Role'; import { User } from '../entity/User'; import { ApiError, HTTPStatus } from '../helpers/error'; import { addQueryWhereClause } from '../helpers/filters'; -import AuthService from './AuthService'; import { Roles } from '../entity/enums/Roles'; // eslint-disable-next-line import/no-cycle -import ContractService from './ContractService'; // eslint-disable-next-line import/no-cycle -import InvoiceService from './InvoiceService'; import FileHelper, { uploadUserAvatarDirLoc, uploadUserBackgroundDirLoc } from '../helpers/fileHelper'; import { IdentityLDAP } from '../entity/IdentityLDAP'; import { ldapEnabled } from '../auth'; import AppDataSource from '../database'; -import validator from 'validator'; +import InvoiceService from './InvoiceService'; +import ContractService from './ContractService'; +import AuthService from './AuthService'; export interface UserParams { email: string; @@ -213,7 +213,7 @@ export default class UserService { }); } user = await this.getUser(user.id); - return user!; + return user; } private validateUserParams(params: UserParams): boolean { diff --git a/src/timedevents/cron.ts b/src/timedevents/cron.ts index 11f9f16..f9cdeea 100644 --- a/src/timedevents/cron.ts +++ b/src/timedevents/cron.ts @@ -1,9 +1,9 @@ import cron from 'node-cron'; +import { ldapEnabled } from '../auth'; import deferredProducts from './events/deferredProducts'; import tmpFolder from './events/tmpFolder'; import directMail from './events/directMail'; import ldapGroups from './events/ldapGroups'; -import { ldapEnabled } from '../auth'; export default function startEvents() { // On July 1st every year, remove the "Deferred" status from all products diff --git a/src/timedevents/events/tmpFolder.ts b/src/timedevents/events/tmpFolder.ts index 64a791c..aa5ddee 100644 --- a/src/timedevents/events/tmpFolder.ts +++ b/src/timedevents/events/tmpFolder.ts @@ -1,6 +1,6 @@ import * as fs from 'fs'; -import { rimraf } from 'rimraf'; import path from 'path'; +import { rimraf } from 'rimraf'; export default async function tmpFolder() { console.log('Remove temp folder...'); From 1b2857b76ceadbdf34c2e357f640539dc6dc3007 Mon Sep 17 00:00:00 2001 From: Gijsdeman Date: Wed, 26 Feb 2025 11:13:37 +0100 Subject: [PATCH 3/9] refactor: lint timedevents --- .eslintrc.js | 30 --- eslint.config.mjs | 6 +- package.json | 5 +- src/timedevents/cron.ts | 18 +- src/timedevents/events/deferredProducts.ts | 6 +- src/timedevents/events/directMail.ts | 12 +- src/timedevents/events/ldapGroups.ts | 18 +- src/timedevents/events/ldapRoles.ts | 31 ++- src/timedevents/events/tmpFolder.ts | 6 +- yarn.lock | 272 +++++++++++---------- 10 files changed, 196 insertions(+), 208 deletions(-) delete mode 100644 .eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 21e3e64..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,30 +0,0 @@ -module.exports = { - root: true, - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint', 'import'], - ignorePatterns: ['dist', 'node_modules'], - rules: { - 'linebreak-style': ['error', 'unix'], - 'lines-between-class-members': [ - 'error', - 'always', - { - exceptAfterSingleLine: true, - }, - ], - 'no-plusplus': 'off', - 'no-console': ['warn', { allow: ['log', 'warn', 'error'] }], - 'import/prefer-default-export': 'off', - 'class-methods-use-this': 'off', - '@typescript-eslint/no-unused-vars': ['warn'], - 'arrow-body-style': 'off', - 'import/no-cycle': 'off', - '@typescript-eslint/no-redeclare': 'off', - 'linebreak-style': ['error', 'windows'], - }, - overrides: [ - { - files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.mjs', '**/*.cjs'], - }, - ], -}; diff --git a/eslint.config.mjs b/eslint.config.mjs index 865f96e..1549883 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -6,8 +6,8 @@ export default [ // TODO should move to eslint-config-typescript { rules: { - "import/no-named-as-default-member": "off" - } + 'import/no-named-as-default-member': 'off', + }, }, - prettier + prettier, ]; diff --git a/package.json b/package.json index ee5d9b2..565dd70 100644 --- a/package.json +++ b/package.json @@ -71,11 +71,8 @@ "@types/swagger-ui-express": "^4.1.8", "@types/uuid": "^10.0.0", "@types/validator": "^13.12.2", - "@typescript-eslint/eslint-plugin": "^8.25.0", - "@typescript-eslint/parser": "^8.25.0", "concurrently": "^9.1.2", - "eslint": "^8.57.1", - "eslint-plugin-import": "^2.31.0", + "eslint": "^9.21.0", "nodemon": "^3.1.9", "ts-node": "^10.9.2", "typescript": "^5.7.3" diff --git a/src/timedevents/cron.ts b/src/timedevents/cron.ts index f9cdeea..7c190d1 100644 --- a/src/timedevents/cron.ts +++ b/src/timedevents/cron.ts @@ -7,24 +7,24 @@ import ldapGroups from './events/ldapGroups'; export default function startEvents() { // On July 1st every year, remove the "Deferred" status from all products - cron.schedule('0 0 0 1 7 *', async () => { - await deferredProducts(); + cron.schedule('0 0 0 1 7 *', () => { + deferredProducts().catch((err) => console.error(err)); }); // Every night at 4:30, the "tmp" folder is deleted and recreated to preserve disk space - cron.schedule('0 29 3 * * *', async () => { - await tmpFolder(); + cron.schedule('0 29 3 * * *', () => { + tmpFolder().catch((err) => console.error(err)); }); // Every night at 4:30, fetch the current DirectMail information and process it - cron.schedule('0 29 3 * * *', async () => { - await directMail(); + cron.schedule('0 29 3 * * *', () => { + directMail().catch((err) => console.error(err)); }); // Every night at 4:30, update all user roles from LDAP if LDAP is enabled - cron.schedule('0 29 3 * * *', async () => { - if (ldapEnabled()) await ldapGroups(); + cron.schedule('0 29 3 * * *', () => { + if (ldapEnabled()) ldapGroups().catch((err) => console.error(err)); }); - console.log('Scheduled timed events'); + console.warn('Scheduled timed events'); } diff --git a/src/timedevents/events/deferredProducts.ts b/src/timedevents/events/deferredProducts.ts index 32d0c01..2d0ed6d 100644 --- a/src/timedevents/events/deferredProducts.ts +++ b/src/timedevents/events/deferredProducts.ts @@ -2,7 +2,7 @@ import ProductInstanceService from '../../services/ProductInstanceService'; export default async function deferredProducts() { await new ProductInstanceService().removeDeferredStatuses(); - console.log('All "deferred" statuses have been removed!'); - console.log('Good luck to the new board!!!'); - console.log('~ The 39th board of GEWIS'); + console.warn('All "deferred" statuses have been removed!'); + console.warn('Good luck to the new board!!!'); + console.warn('~ The 39th board of GEWIS'); } diff --git a/src/timedevents/events/directMail.ts b/src/timedevents/events/directMail.ts index d023d4e..d148c2e 100644 --- a/src/timedevents/events/directMail.ts +++ b/src/timedevents/events/directMail.ts @@ -1,6 +1,12 @@ import axios from 'axios'; import ProductService from '../../services/ProductService'; +interface DirectMailResponse { + description: string; + eMail: string; + noMembers: string; +} + export default async function directMail() { if ( !process.env.DIRECTMAIL_URL || @@ -20,7 +26,11 @@ export default async function directMail() { }) .then(async (response) => { const header = [['Name', 'Email', 'Students']]; - const parsedData: string[][] = response.data.map((d: any) => [d.description, d.eMail, d.noMembers]); + const parsedData: string[][] = (response.data as DirectMailResponse[]).map((d: DirectMailResponse) => [ + d.description, + d.eMail, + d.noMembers.toString(), + ]); await new ProductService().updatePricing(parseInt(process.env.DIRECTMAIL_PRODUCT_ID!, 10), { data: header.concat(parsedData), }); diff --git a/src/timedevents/events/ldapGroups.ts b/src/timedevents/events/ldapGroups.ts index 9578eea..57e64d9 100644 --- a/src/timedevents/events/ldapGroups.ts +++ b/src/timedevents/events/ldapGroups.ts @@ -1,7 +1,4 @@ -// The @types package from ldapjs is not installed, because it causes -// a conflict in TSOA with passport-ldapauth @types -// @ts-ignore -import { createClient } from 'ldapjs'; +import { createClient, SearchCallbackResponse, SearchEntry } from 'ldapjs'; import { IdentityLDAP } from '../../entity/IdentityLDAP'; import { updateUserInformation } from '../../auth'; import AppDataSource from '../../database'; @@ -24,13 +21,18 @@ export default async function ldapGroups() { scope: 'one', filter: (process.env.LDAP_SEARCHFILTER || '').replace('{{username}}', identity.username), }, - (err: any, res: any) => { - res.on('searchEntry', async (entry: any) => { - await updateUserInformation(identity.user, entry.object); + (err: Error | null, res: SearchCallbackResponse) => { + if (err) { + console.error(err); + return; + } + + res.on('searchEntry', (entry: SearchEntry) => { + updateUserInformation(identity.user, entry.object).catch((err) => console.error(err)); }); }, ); }); - console.log('Updated user roles based on LDAP'); + console.warn('Updated user roles based on LDAP'); } diff --git a/src/timedevents/events/ldapRoles.ts b/src/timedevents/events/ldapRoles.ts index 836a5c2..1eaed1a 100644 --- a/src/timedevents/events/ldapRoles.ts +++ b/src/timedevents/events/ldapRoles.ts @@ -1,9 +1,12 @@ -// @ts-ignore -import { createClient } from 'ldapjs'; +import { createClient, LDAPResult, SearchCallbackResponse, SearchEntry, SearchRequest } from 'ldapjs'; import dotenv from 'dotenv'; import { ldapEnabled } from '../../auth'; import AuthService from '../../services/AuthService'; +export interface SearchReference { + uris: string[]; +} + export default async function ldapRoles() { dotenv.config(); @@ -23,30 +26,32 @@ export default async function ldapRoles() { { filter: process.env.LDAP_SEARCHFILTER!.replace('username', identity.username), }, - (error: any, res: any) => { + (error: Error | null, res: SearchCallbackResponse) => { if (error) { console.error(error); return; } - res.on('searchRequest', (searchRequest: any) => { - console.log('searchRequest: ', searchRequest); + res.on('searchRequest', (searchRequest: SearchRequest) => { + console.warn('searchRequest: ', searchRequest); }); - res.on('searchEntry', (entry: any) => { - console.log(`entry: ${JSON.stringify(entry.object)}`); + res.on('searchEntry', (entry: SearchEntry) => { + console.warn(`entry: ${JSON.stringify(entry.object)}`); }); - res.on('searchReference', (referral: any) => { - console.log(`referral: ${referral.uris.join()}`); + res.on('searchReference', (referral: SearchReference) => { + console.warn(`referral: ${referral.uris.join()}`); }); - res.on('error', (err: any) => { + res.on('error', (err: Error) => { console.error(`error: ${err.message}`); }); - res.on('end', (result: any) => { - console.log(`status: ${result}`); + res.on('end', (result: LDAPResult | null) => { + console.warn(`status: ${JSON.stringify(result)}`); }); }, ); }); } -ldapRoles().then(() => Promise.resolve()); +ldapRoles() + .then(() => Promise.resolve()) + .catch((err) => console.error(err)); diff --git a/src/timedevents/events/tmpFolder.ts b/src/timedevents/events/tmpFolder.ts index aa5ddee..52e54e1 100644 --- a/src/timedevents/events/tmpFolder.ts +++ b/src/timedevents/events/tmpFolder.ts @@ -3,9 +3,9 @@ import path from 'path'; import { rimraf } from 'rimraf'; export default async function tmpFolder() { - console.log('Remove temp folder...'); + console.warn('Remove temp folder...'); await rimraf(path.join(__dirname, '../../../tmp')); - console.log('Folder deleted'); + console.warn('Folder deleted'); fs.mkdirSync(path.join(__dirname, '../../../tmp')); - console.log('Removed and recreated a new "tmp" folder for temporary files'); + console.warn('Removed and recreated a new "tmp" folder for temporary files'); } diff --git a/yarn.lock b/yarn.lock index b1d5de4..c94c276 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,7 +25,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.6.1": +"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.12.1": version: 4.12.1 resolution: "@eslint-community/regexpp@npm:4.12.1" checksum: 10c0/a03d98c246bcb9109aec2c08e4d10c8d010256538dcb3f56610191607214523d4fb1b00aa81df830b6dffb74c5fa0be03642513a289c567949d3e550ca11cdf6 @@ -44,20 +44,40 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.1.4": - version: 2.1.4 - resolution: "@eslint/eslintrc@npm:2.1.4" +"@eslint/config-array@npm:^0.19.2": + version: 0.19.2 + resolution: "@eslint/config-array@npm:0.19.2" + dependencies: + "@eslint/object-schema": "npm:^2.1.6" + debug: "npm:^4.3.1" + minimatch: "npm:^3.1.2" + checksum: 10c0/dd68da9abb32d336233ac4fe0db1e15a0a8d794b6e69abb9e57545d746a97f6f542496ff9db0d7e27fab1438546250d810d90b1904ac67677215b8d8e7573f3d + languageName: node + linkType: hard + +"@eslint/core@npm:^0.12.0": + version: 0.12.0 + resolution: "@eslint/core@npm:0.12.0" + dependencies: + "@types/json-schema": "npm:^7.0.15" + checksum: 10c0/d032af81195bb28dd800c2b9617548c6c2a09b9490da3c5537fd2a1201501666d06492278bb92cfccac1f7ac249e58601dd87f813ec0d6a423ef0880434fa0c3 + languageName: node + linkType: hard + +"@eslint/eslintrc@npm:^3.3.0": + version: 3.3.0 + resolution: "@eslint/eslintrc@npm:3.3.0" dependencies: ajv: "npm:^6.12.4" debug: "npm:^4.3.2" - espree: "npm:^9.6.0" - globals: "npm:^13.19.0" + espree: "npm:^10.0.1" + globals: "npm:^14.0.0" ignore: "npm:^5.2.0" import-fresh: "npm:^3.2.1" js-yaml: "npm:^4.1.0" minimatch: "npm:^3.1.2" strip-json-comments: "npm:^3.1.1" - checksum: 10c0/32f67052b81768ae876c84569ffd562491ec5a5091b0c1e1ca1e0f3c24fb42f804952fdd0a137873bc64303ba368a71ba079a6f691cee25beee9722d94cc8573 + checksum: 10c0/215de990231b31e2fe6458f225d8cea0f5c781d3ecb0b7920703501f8cd21b3101fc5ef2f0d4f9a38865d36647b983e0e8ce8bf12fd2bcdd227fc48a5b1a43be languageName: node linkType: hard @@ -68,10 +88,20 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.57.1": - version: 8.57.1 - resolution: "@eslint/js@npm:8.57.1" - checksum: 10c0/b489c474a3b5b54381c62e82b3f7f65f4b8a5eaaed126546520bf2fede5532a8ed53212919fed1e9048dcf7f37167c8561d58d0ba4492a4244004e7793805223 +"@eslint/object-schema@npm:^2.1.6": + version: 2.1.6 + resolution: "@eslint/object-schema@npm:2.1.6" + checksum: 10c0/b8cdb7edea5bc5f6a96173f8d768d3554a628327af536da2fc6967a93b040f2557114d98dbcdbf389d5a7b290985ad6a9ce5babc547f36fc1fde42e674d11a56 + languageName: node + linkType: hard + +"@eslint/plugin-kit@npm:^0.2.7": + version: 0.2.7 + resolution: "@eslint/plugin-kit@npm:0.2.7" + dependencies: + "@eslint/core": "npm:^0.12.0" + levn: "npm:^0.4.1" + checksum: 10c0/0a1aff1ad63e72aca923217e556c6dfd67d7cd121870eb7686355d7d1475d569773528a8b2111b9176f3d91d2ea81f7413c34600e8e5b73d59e005d70780b633 languageName: node linkType: hard @@ -428,14 +458,20 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.13.0": - version: 0.13.0 - resolution: "@humanwhocodes/config-array@npm:0.13.0" +"@humanfs/core@npm:^0.19.1": + version: 0.19.1 + resolution: "@humanfs/core@npm:0.19.1" + checksum: 10c0/aa4e0152171c07879b458d0e8a704b8c3a89a8c0541726c6b65b81e84fd8b7564b5d6c633feadc6598307d34564bd53294b533491424e8e313d7ab6c7bc5dc67 + languageName: node + linkType: hard + +"@humanfs/node@npm:^0.16.6": + version: 0.16.6 + resolution: "@humanfs/node@npm:0.16.6" dependencies: - "@humanwhocodes/object-schema": "npm:^2.0.3" - debug: "npm:^4.3.1" - minimatch: "npm:^3.0.5" - checksum: 10c0/205c99e756b759f92e1f44a3dc6292b37db199beacba8f26c2165d4051fe73a4ae52fdcfd08ffa93e7e5cb63da7c88648f0e84e197d154bbbbe137b2e0dd332e + "@humanfs/core": "npm:^0.19.1" + "@humanwhocodes/retry": "npm:^0.3.0" + checksum: 10c0/8356359c9f60108ec204cbd249ecd0356667359b2524886b357617c4a7c3b6aace0fd5a369f63747b926a762a88f8a25bc066fa1778508d110195ce7686243e1 languageName: node linkType: hard @@ -446,10 +482,17 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^2.0.3": - version: 2.0.3 - resolution: "@humanwhocodes/object-schema@npm:2.0.3" - checksum: 10c0/80520eabbfc2d32fe195a93557cef50dfe8c8905de447f022675aaf66abc33ae54098f5ea78548d925aa671cd4ab7c7daa5ad704fe42358c9b5e7db60f80696c +"@humanwhocodes/retry@npm:^0.3.0": + version: 0.3.1 + resolution: "@humanwhocodes/retry@npm:0.3.1" + checksum: 10c0/f0da1282dfb45e8120480b9e2e275e2ac9bbe1cf016d046fdad8e27cc1285c45bb9e711681237944445157b430093412b4446c1ab3fc4bb037861b5904101d3b + languageName: node + linkType: hard + +"@humanwhocodes/retry@npm:^0.4.2": + version: 0.4.2 + resolution: "@humanwhocodes/retry@npm:0.4.2" + checksum: 10c0/0235525d38f243bee3bf8b25ed395fbf957fb51c08adae52787e1325673071abe856c7e18e530922ed2dd3ce12ed82ba01b8cee0279ac52a3315fcdc3a69ef0c languageName: node linkType: hard @@ -606,7 +649,7 @@ __metadata: languageName: node linkType: hard -"@nodelib/fs.walk@npm:^1.2.3, @nodelib/fs.walk@npm:^1.2.8": +"@nodelib/fs.walk@npm:^1.2.3": version: 1.2.8 resolution: "@nodelib/fs.walk@npm:1.2.8" dependencies: @@ -840,6 +883,13 @@ __metadata: languageName: node linkType: hard +"@types/estree@npm:^1.0.6": + version: 1.0.6 + resolution: "@types/estree@npm:1.0.6" + checksum: 10c0/cdfd751f6f9065442cd40957c07fd80361c962869aa853c1c2fd03e101af8b9389d8ff4955a43a6fcfa223dd387a089937f95be0f3eec21ca527039fd2d9859a + languageName: node + linkType: hard + "@types/express-serve-static-core@npm:^5.0.0": version: 5.0.6 resolution: "@types/express-serve-static-core@npm:5.0.6" @@ -887,6 +937,13 @@ __metadata: languageName: node linkType: hard +"@types/json-schema@npm:^7.0.15": + version: 7.0.15 + resolution: "@types/json-schema@npm:7.0.15" + checksum: 10c0/a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db + languageName: node + linkType: hard + "@types/json5@npm:^0.0.29": version: 0.0.29 resolution: "@types/json5@npm:0.0.29" @@ -1132,7 +1189,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.25.0, @typescript-eslint/eslint-plugin@npm:^8.25.0": +"@typescript-eslint/eslint-plugin@npm:8.25.0": version: 8.25.0 resolution: "@typescript-eslint/eslint-plugin@npm:8.25.0" dependencies: @@ -1153,7 +1210,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.25.0, @typescript-eslint/parser@npm:^8.25.0": +"@typescript-eslint/parser@npm:8.25.0": version: 8.25.0 resolution: "@typescript-eslint/parser@npm:8.25.0" dependencies: @@ -1244,13 +1301,6 @@ __metadata: languageName: node linkType: hard -"@ungap/structured-clone@npm:^1.2.0": - version: 1.3.0 - resolution: "@ungap/structured-clone@npm:1.3.0" - checksum: 10c0/0fc3097c2540ada1fc340ee56d58d96b5b536a2a0dab6e3ec17d4bfc8c4c86db345f61a375a8185f9da96f01c69678f836a2b57eeaa9e4b8eeafd26428e57b0a - languageName: node - linkType: hard - "@vue/eslint-config-prettier@npm:^10.2.0": version: 10.2.0 resolution: "@vue/eslint-config-prettier@npm:10.2.0" @@ -1315,7 +1365,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.11.0, acorn@npm:^8.4.1, acorn@npm:^8.9.0": +"acorn@npm:^8.11.0, acorn@npm:^8.14.0, acorn@npm:^8.4.1": version: 8.14.0 resolution: "acorn@npm:8.14.0" bin: @@ -1998,7 +2048,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.6": +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" dependencies: @@ -2168,15 +2218,6 @@ __metadata: languageName: node linkType: hard -"doctrine@npm:^3.0.0": - version: 3.0.0 - resolution: "doctrine@npm:3.0.0" - dependencies: - esutils: "npm:^2.0.2" - checksum: 10c0/c96bdccabe9d62ab6fea9399fdff04a66e6563c1d6fb3a3a063e8d53c3bb136ba63e84250bbf63d00086a769ad53aef92d2bd483f03f837fc97b71cbee6b2520 - languageName: node - linkType: hard - "dotenv@npm:^16.0.3, dotenv@npm:^16.4.7": version: 16.4.7 resolution: "dotenv@npm:16.4.7" @@ -2530,17 +2571,17 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:^7.2.2": - version: 7.2.2 - resolution: "eslint-scope@npm:7.2.2" +"eslint-scope@npm:^8.2.0": + version: 8.2.0 + resolution: "eslint-scope@npm:8.2.0" dependencies: esrecurse: "npm:^4.3.0" estraverse: "npm:^5.2.0" - checksum: 10c0/613c267aea34b5a6d6c00514e8545ef1f1433108097e857225fed40d397dd6b1809dffd11c2fde23b37ca53d7bf935fe04d2a18e6fc932b31837b6ad67e1c116 + checksum: 10c0/8d2d58e2136d548ac7e0099b1a90d9fab56f990d86eb518de1247a7066d38c908be2f3df477a79cf60d70b30ba18735d6c6e70e9914dca2ee515a729975d70d6 languageName: node linkType: hard -"eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": +"eslint-visitor-keys@npm:^3.4.3": version: 3.4.3 resolution: "eslint-visitor-keys@npm:3.4.3" checksum: 10c0/92708e882c0a5ffd88c23c0b404ac1628cf20104a108c745f240a13c332a11aac54f49a22d5762efbffc18ecbc9a580d1b7ad034bf5f3cc3307e5cbff2ec9820 @@ -2554,66 +2595,67 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.57.1": - version: 8.57.1 - resolution: "eslint@npm:8.57.1" +"eslint@npm:^9.21.0": + version: 9.21.0 + resolution: "eslint@npm:9.21.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" - "@eslint-community/regexpp": "npm:^4.6.1" - "@eslint/eslintrc": "npm:^2.1.4" - "@eslint/js": "npm:8.57.1" - "@humanwhocodes/config-array": "npm:^0.13.0" + "@eslint-community/regexpp": "npm:^4.12.1" + "@eslint/config-array": "npm:^0.19.2" + "@eslint/core": "npm:^0.12.0" + "@eslint/eslintrc": "npm:^3.3.0" + "@eslint/js": "npm:9.21.0" + "@eslint/plugin-kit": "npm:^0.2.7" + "@humanfs/node": "npm:^0.16.6" "@humanwhocodes/module-importer": "npm:^1.0.1" - "@nodelib/fs.walk": "npm:^1.2.8" - "@ungap/structured-clone": "npm:^1.2.0" + "@humanwhocodes/retry": "npm:^0.4.2" + "@types/estree": "npm:^1.0.6" + "@types/json-schema": "npm:^7.0.15" ajv: "npm:^6.12.4" chalk: "npm:^4.0.0" - cross-spawn: "npm:^7.0.2" + cross-spawn: "npm:^7.0.6" debug: "npm:^4.3.2" - doctrine: "npm:^3.0.0" escape-string-regexp: "npm:^4.0.0" - eslint-scope: "npm:^7.2.2" - eslint-visitor-keys: "npm:^3.4.3" - espree: "npm:^9.6.1" - esquery: "npm:^1.4.2" + eslint-scope: "npm:^8.2.0" + eslint-visitor-keys: "npm:^4.2.0" + espree: "npm:^10.3.0" + esquery: "npm:^1.5.0" esutils: "npm:^2.0.2" fast-deep-equal: "npm:^3.1.3" - file-entry-cache: "npm:^6.0.1" + file-entry-cache: "npm:^8.0.0" find-up: "npm:^5.0.0" glob-parent: "npm:^6.0.2" - globals: "npm:^13.19.0" - graphemer: "npm:^1.4.0" ignore: "npm:^5.2.0" imurmurhash: "npm:^0.1.4" is-glob: "npm:^4.0.0" - is-path-inside: "npm:^3.0.3" - js-yaml: "npm:^4.1.0" json-stable-stringify-without-jsonify: "npm:^1.0.1" - levn: "npm:^0.4.1" lodash.merge: "npm:^4.6.2" minimatch: "npm:^3.1.2" natural-compare: "npm:^1.4.0" optionator: "npm:^0.9.3" - strip-ansi: "npm:^6.0.1" - text-table: "npm:^0.2.0" + peerDependencies: + jiti: "*" + peerDependenciesMeta: + jiti: + optional: true bin: eslint: bin/eslint.js - checksum: 10c0/1fd31533086c1b72f86770a4d9d7058ee8b4643fd1cfd10c7aac1ecb8725698e88352a87805cf4b2ce890aa35947df4b4da9655fb7fdfa60dbb448a43f6ebcf1 + checksum: 10c0/558edb25b440cd51825d66fed3e84f1081bd6f4cb2cf994e60ece4c5978fa0583e88b75faf187c1fc21688c4ff7072f12bf5f6d1be1e09a4d6af78cff39dc520 languageName: node linkType: hard -"espree@npm:^9.6.0, espree@npm:^9.6.1": - version: 9.6.1 - resolution: "espree@npm:9.6.1" +"espree@npm:^10.0.1, espree@npm:^10.3.0": + version: 10.3.0 + resolution: "espree@npm:10.3.0" dependencies: - acorn: "npm:^8.9.0" + acorn: "npm:^8.14.0" acorn-jsx: "npm:^5.3.2" - eslint-visitor-keys: "npm:^3.4.1" - checksum: 10c0/1a2e9b4699b715347f62330bcc76aee224390c28bb02b31a3752e9d07549c473f5f986720483c6469cf3cfb3c9d05df612ffc69eb1ee94b54b739e67de9bb460 + eslint-visitor-keys: "npm:^4.2.0" + checksum: 10c0/272beeaca70d0a1a047d61baff64db04664a33d7cfb5d144f84bc8a5c6194c6c8ebe9cc594093ca53add88baa23e59b01e69e8a0160ab32eac570482e165c462 languageName: node linkType: hard -"esquery@npm:^1.4.2": +"esquery@npm:^1.5.0": version: 1.6.0 resolution: "esquery@npm:1.6.0" dependencies: @@ -2817,12 +2859,12 @@ __metadata: languageName: node linkType: hard -"file-entry-cache@npm:^6.0.1": - version: 6.0.1 - resolution: "file-entry-cache@npm:6.0.1" +"file-entry-cache@npm:^8.0.0": + version: 8.0.0 + resolution: "file-entry-cache@npm:8.0.0" dependencies: - flat-cache: "npm:^3.0.4" - checksum: 10c0/58473e8a82794d01b38e5e435f6feaf648e3f36fdb3a56e98f417f4efae71ad1c0d4ebd8a9a7c50c3ad085820a93fc7494ad721e0e4ebc1da3573f4e1c3c7cdd + flat-cache: "npm:^4.0.0" + checksum: 10c0/9e2b5938b1cd9b6d7e3612bdc533afd4ac17b2fc646569e9a8abbf2eb48e5eb8e316bc38815a3ef6a1b456f4107f0d0f055a614ca613e75db6bf9ff4d72c1638 languageName: node linkType: hard @@ -2860,14 +2902,13 @@ __metadata: languageName: node linkType: hard -"flat-cache@npm:^3.0.4": - version: 3.2.0 - resolution: "flat-cache@npm:3.2.0" +"flat-cache@npm:^4.0.0": + version: 4.0.1 + resolution: "flat-cache@npm:4.0.1" dependencies: flatted: "npm:^3.2.9" - keyv: "npm:^4.5.3" - rimraf: "npm:^3.0.2" - checksum: 10c0/b76f611bd5f5d68f7ae632e3ae503e678d205cf97a17c6ab5b12f6ca61188b5f1f7464503efae6dc18683ed8f0b41460beb48ac4b9ac63fe6201296a91ba2f75 + keyv: "npm:^4.5.4" + checksum: 10c0/2c59d93e9faa2523e4fda6b4ada749bed432cfa28c8e251f33b25795e426a1c6dbada777afb1f74fcfff33934fdbdea921ee738fcc33e71adc9d6eca984a1cfc languageName: node linkType: hard @@ -3163,12 +3204,10 @@ __metadata: languageName: node linkType: hard -"globals@npm:^13.19.0": - version: 13.24.0 - resolution: "globals@npm:13.24.0" - dependencies: - type-fest: "npm:^0.20.2" - checksum: 10c0/d3c11aeea898eb83d5ec7a99508600fbe8f83d2cf00cbb77f873dbf2bcb39428eff1b538e4915c993d8a3b3473fa71eeebfe22c9bb3a3003d1e26b1f2c8a42cd +"globals@npm:^14.0.0": + version: 14.0.0 + resolution: "globals@npm:14.0.0" + checksum: 10c0/b96ff42620c9231ad468d4c58ff42afee7777ee1c963013ff8aabe095a451d0ceeb8dcd8ef4cbd64d2538cef45f787a78ba3a9574f4a634438963e334471302d languageName: node linkType: hard @@ -3627,13 +3666,6 @@ __metadata: languageName: node linkType: hard -"is-path-inside@npm:^3.0.3": - version: 3.0.3 - resolution: "is-path-inside@npm:3.0.3" - checksum: 10c0/cf7d4ac35fb96bab6a1d2c3598fe5ebb29aafb52c0aaa482b5a3ed9d8ba3edc11631e3ec2637660c44b3ce0e61a08d54946e8af30dec0b60a7c27296c68ffd05 - languageName: node - linkType: hard - "is-property@npm:^1.0.2": version: 1.0.2 resolution: "is-property@npm:1.0.2" @@ -3925,7 +3957,7 @@ __metadata: languageName: node linkType: hard -"keyv@npm:^4.5.3": +"keyv@npm:^4.5.4": version: 4.5.4 resolution: "keyv@npm:4.5.4" dependencies: @@ -4306,7 +4338,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": +"minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" dependencies: @@ -4845,16 +4877,13 @@ __metadata: "@types/swagger-ui-express": "npm:^4.1.8" "@types/uuid": "npm:^10.0.0" "@types/validator": "npm:^13.12.2" - "@typescript-eslint/eslint-plugin": "npm:^8.25.0" - "@typescript-eslint/parser": "npm:^8.25.0" axios: "npm:^1.7.9" body-parser: "npm:^1.20.3" concurrently: "npm:^9.1.2" connect-typeorm: "npm:^2.0.0" cors: "npm:^2.8.5" dotenv: "npm:^16.4.7" - eslint: "npm:^8.57.1" - eslint-plugin-import: "npm:^2.31.0" + eslint: "npm:^9.21.0" express: "npm:^4.21.2" express-session: "npm:^1.18.1" express-validator: "npm:^7.2.1" @@ -5438,17 +5467,6 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:^3.0.2": - version: 3.0.2 - resolution: "rimraf@npm:3.0.2" - dependencies: - glob: "npm:^7.1.3" - bin: - rimraf: bin.js - checksum: 10c0/9cb7757acb489bd83757ba1a274ab545eafd75598a9d817e0c3f8b164238dd90eba50d6b848bd4dcc5f3040912e882dc7ba71653e35af660d77b25c381d402e8 - languageName: node - linkType: hard - "rimraf@npm:^5.0.5": version: 5.0.10 resolution: "rimraf@npm:5.0.10" @@ -6088,13 +6106,6 @@ __metadata: languageName: node linkType: hard -"text-table@npm:^0.2.0": - version: 0.2.0 - resolution: "text-table@npm:0.2.0" - checksum: 10c0/02805740c12851ea5982686810702e2f14369a5f4c5c40a836821e3eefc65ffeec3131ba324692a37608294b0fd8c1e55a2dd571ffed4909822787668ddbee5c - languageName: node - linkType: hard - "thenify-all@npm:^1.0.0": version: 1.6.0 resolution: "thenify-all@npm:1.6.0" @@ -6261,13 +6272,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^0.20.2": - version: 0.20.2 - resolution: "type-fest@npm:0.20.2" - checksum: 10c0/dea9df45ea1f0aaa4e2d3bed3f9a0bfe9e5b2592bddb92eb1bf06e50bcf98dbb78189668cd8bc31a0511d3fc25539b4cd5c704497e53e93e2d40ca764b10bfc3 - languageName: node - linkType: hard - "type-is@npm:^1.6.4, type-is@npm:~1.6.18": version: 1.6.18 resolution: "type-is@npm:1.6.18" From b76307d46319b46aff4ce7ad652bb6d376633917 Mon Sep 17 00:00:00 2001 From: Gijsdeman Date: Wed, 26 Feb 2025 13:06:55 +0100 Subject: [PATCH 4/9] refactor: lint services --- src/services/ActivityService.ts | 13 ++++----- src/services/AuthService.ts | 39 ++++++++++++++++---------- src/services/CompanyService.ts | 2 +- src/services/ContactService.ts | 2 +- src/services/FileService.ts | 2 ++ src/services/ProductCategoryService.ts | 2 +- src/services/ProductInstanceService.ts | 4 +-- src/services/StatisticsService.ts | 5 ++-- src/services/UserService.ts | 4 +-- 9 files changed, 39 insertions(+), 34 deletions(-) diff --git a/src/services/ActivityService.ts b/src/services/ActivityService.ts index be960ce..faefece 100644 --- a/src/services/ActivityService.ts +++ b/src/services/ActivityService.ts @@ -1,3 +1,5 @@ +/* eslint-disable */ +// TODO this file needs to be refactored with generics to be linted properly import { Repository } from 'typeorm'; import BaseActivity from '../entity/activity/BaseActivity'; import { ContractActivity } from '../entity/activity/ContractActivity'; @@ -5,14 +7,11 @@ import { InvoiceActivity } from '../entity/activity/InvoiceActivity'; import { ProductInstanceActivity } from '../entity/activity/ProductInstanceActivity'; import { ApiError, HTTPStatus } from '../helpers/error'; import { User } from '../entity/User'; -// eslint-disable-next-line import/no-cycle -// eslint-disable-next-line import/no-cycle import { Contract } from '../entity/Contract'; import { ActivityType } from '../entity/enums/ActivityType'; import { ContractStatus } from '../entity/enums/ContractStatus'; import { InvoiceStatus } from '../entity/enums/InvoiceStatus'; import { ProductInstanceStatus } from '../entity/enums/ProductActivityStatus'; -// eslint-disable-next-line import/no-cycle import { sendInvoiceEmails } from '../helpers/mailBuilder'; import { appendProductActivityDescription, createAddProductActivityDescription } from '../helpers/activity'; import { Language } from '../entity/enums/Language'; @@ -189,11 +188,11 @@ export default class ActivityService { switch (act.constructor.name) { case 'ContractActivity': activity = act; - // eslint-disable-next-line no-case-declarations + const contract = await new ContractService().getContract(activity.contractId); - // eslint-disable-next-line no-case-declarations + const canEndContract = await this.canEndContract(contract); - // eslint-disable-next-line no-case-declarations + statuses = await this.getStatuses({ contractId: activity.contractId }); if (!canEndContract.cancelled && activity.subType === ContractStatus.CANCELLED) { @@ -289,7 +288,7 @@ export default class ActivityService { * @param C * @param params Parameters to create an activity with */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + async createActivity(C: { new (): T }, params: FullActivityParams): Promise { // @ts-ignore let activity = new C(); diff --git a/src/services/AuthService.ts b/src/services/AuthService.ts index c3284ac..2d02b1e 100644 --- a/src/services/AuthService.ts +++ b/src/services/AuthService.ts @@ -1,6 +1,6 @@ import express from 'express'; import { Repository } from 'typeorm'; -import jwt from 'jsonwebtoken'; +import jwt, { JwtPayload } from 'jsonwebtoken'; import validator from 'validator'; import { IdentityLocal } from '../entity/IdentityLocal'; import { User } from '../entity/User'; @@ -28,6 +28,11 @@ export interface LdapIdentityParams { username: string; } +interface JwtToken { + user_id: number; + type: string; +} + export default class AuthService { identityLocalRepo: Repository; @@ -49,7 +54,7 @@ export default class AuthService { this.userRepo = userRepo ?? AppDataSource.getRepository(User); } - async getAuthStatus(req: express.Request): Promise { + getAuthStatus(req: express.Request): AuthStatus { const authenticated = req.isAuthenticated(); return { @@ -74,18 +79,20 @@ export default class AuthService { return this.identityLdapRepo.find({ relations: ['user'] }); } + // TODO check error type in case of reject async logout(req: express.Request): Promise { return new Promise((resolve, reject) => { - req.logout((error) => { + req.logout((error: Error) => { if (error) reject(error); resolve(); }); }); } + // TODO check error type in case of reject login(user: User, req: express.Request) { return new Promise((resolve, reject) => { - req.logIn(user, (err) => { + req.logIn(user, (err: Error) => { if (err) { return reject(err); } @@ -106,7 +113,7 @@ export default class AuthService { return; } - Mailer.getInstance().send( + await Mailer.getInstance().send( resetPassword( user, `${process.env.SERVER_HOST}/reset-password?token=${this.getResetPasswordToken(user, identity)}`, @@ -128,7 +135,7 @@ export default class AuthService { identity = (await this.identityLocalRepo.findOneBy({ id: user.id }))!; if (!silent) { - Mailer.getInstance().send( + await Mailer.getInstance().send( newUser(user, `${process.env.SERVER_HOST}/reset-password?token=${this.getSetPasswordToken(user, identity)}`), ); } @@ -173,7 +180,7 @@ export default class AuthService { user_id: user.id, }, // Password salt + user createdAt as unique key - `${identity.salt || ''}.${user.createdAt}`, + `${identity.salt || ''}.${user.createdAt.toString()}`, { expiresIn: '7 days' }, ); } @@ -185,14 +192,18 @@ export default class AuthService { user_id: user.id, }, // Password salt + user createdAt as unique key - `${identity.salt || ''}.${user.createdAt}`, + `${identity.salt || ''}.${user.createdAt.toString()}`, { expiresIn: '7 days' }, ); } + checkToken(token: string | JwtPayload | null): token is JwtToken { + return token != null && typeof token === 'object' && 'used_id' in token; + } + async resetPassword(newPassword: string, tokenString: string): Promise { const token = jwt.decode(tokenString); - if (!(token && typeof token !== 'string')) { + if (!this.checkToken(token)) { throw new ApiError(HTTPStatus.BadRequest, INVALID_TOKEN); } @@ -208,7 +219,7 @@ export default class AuthService { case 'PASSWORD_RESET': case 'PASSWORD_SET': { // Verify the token - jwt.verify(tokenString, `${identity.salt || ''}.${user.createdAt}`); + jwt.verify(tokenString, `${identity.salt || ''}.${user.createdAt.toString()}`); const salt = generateSalt(); await this.identityLocalRepo.update(user.id, { id: user.id, @@ -219,10 +230,8 @@ export default class AuthService { }); return; } - default: - throw new ApiError(HTTPStatus.BadRequest, INVALID_TOKEN); } - } catch (e) { + } catch { throw new ApiError(HTTPStatus.BadRequest, INVALID_TOKEN); } } @@ -240,7 +249,7 @@ export default class AuthService { throw new ApiError(HTTPStatus.BadRequest, "You don't have an API key yet."); } - Mailer.getInstance().send(viewApiKey(user, `${process.env.SERVER_HOST}/`)); + await Mailer.getInstance().send(viewApiKey(user, `${process.env.SERVER_HOST}/`)); return identity.apiKey; } @@ -261,7 +270,7 @@ export default class AuthService { await this.identityApiKeyRepo.insert(identity); - Mailer.getInstance().send(newApiKey(user, `${process.env.SERVER_HOST}/`)); + await Mailer.getInstance().send(newApiKey(user, `${process.env.SERVER_HOST}/`)); return identity.apiKey; } diff --git a/src/services/CompanyService.ts b/src/services/CompanyService.ts index b05d81f..1afe2d0 100644 --- a/src/services/CompanyService.ts +++ b/src/services/CompanyService.ts @@ -98,7 +98,7 @@ export default class CompanyService { createCompany(params: CompanyParams): Promise { const company = { ...params, - } as any as Company; + } as Company; return this.repo.save(company); } diff --git a/src/services/ContactService.ts b/src/services/ContactService.ts index 978341e..a5d77d4 100644 --- a/src/services/ContactService.ts +++ b/src/services/ContactService.ts @@ -83,7 +83,7 @@ export default class ContactService { async createContact(params: ContactParams): Promise { const contact = { ...params, - } as any as Contact; + } as Contact; return this.repo.save(contact); } diff --git a/src/services/FileService.ts b/src/services/FileService.ts index af40c47..82a12fb 100644 --- a/src/services/FileService.ts +++ b/src/services/FileService.ts @@ -1,3 +1,5 @@ +/* eslint-disable */ +// TODO this file needs to be refactored with generics to be linted properly import * as fs from 'fs'; import path from 'path'; import { v4 as uuidv4 } from 'uuid'; diff --git a/src/services/ProductCategoryService.ts b/src/services/ProductCategoryService.ts index 9406b4a..fa3a67c 100644 --- a/src/services/ProductCategoryService.ts +++ b/src/services/ProductCategoryService.ts @@ -60,7 +60,7 @@ export default class ProductCategoryService { async createCategory(params: CategoryParams): Promise { const category = { ...params, - } as any as ProductCategory; + } as ProductCategory; return this.repo.save(category); } diff --git a/src/services/ProductInstanceService.ts b/src/services/ProductInstanceService.ts index 4489617..dc76c7c 100644 --- a/src/services/ProductInstanceService.ts +++ b/src/services/ProductInstanceService.ts @@ -1,8 +1,6 @@ import { FindManyOptions, IsNull, Not, Repository } from 'typeorm'; import { ProductInstance } from '../entity/ProductInstance'; import { ApiError, HTTPStatus } from '../helpers/error'; -// eslint-disable-next-line import/no-cycle -// eslint-disable-next-line import/no-cycle import { ProductInstanceActivity } from '../entity/activity/ProductInstanceActivity'; import { User } from '../entity/User'; import { ContractActivity } from '../entity/activity/ContractActivity'; @@ -61,7 +59,7 @@ export default class ProductInstanceService { let productInstance = { ...params, contractId, - } as any as ProductInstance; + } as ProductInstance; if (product.status === ProductStatus.INACTIVE) { throw new ApiError(HTTPStatus.BadRequest, 'Cannot add inactive products to contracts'); diff --git a/src/services/StatisticsService.ts b/src/services/StatisticsService.ts index af0f5b8..b042e01 100644 --- a/src/services/StatisticsService.ts +++ b/src/services/StatisticsService.ts @@ -46,8 +46,7 @@ export default class StatisticsService { .getOne(); let start: Date; if (startYear) { - // @ts-ignore - start = startYear.createdAt; + start = startYear.createdAt as Date; } else { start = new Date(); } @@ -189,7 +188,7 @@ export default class StatisticsService { amount: 0, nrOfProducts: 0, year: result[0].year + i, - } as any as AnalysisResultByYear); + } as AnalysisResultByYear); } } diff --git a/src/services/UserService.ts b/src/services/UserService.ts index 392cc1a..47be132 100644 --- a/src/services/UserService.ts +++ b/src/services/UserService.ts @@ -9,8 +9,6 @@ import { User } from '../entity/User'; import { ApiError, HTTPStatus } from '../helpers/error'; import { addQueryWhereClause } from '../helpers/filters'; import { Roles } from '../entity/enums/Roles'; -// eslint-disable-next-line import/no-cycle -// eslint-disable-next-line import/no-cycle import FileHelper, { uploadUserAvatarDirLoc, uploadUserBackgroundDirLoc } from '../helpers/fileHelper'; import { IdentityLDAP } from '../entity/IdentityLDAP'; import { ldapEnabled } from '../auth'; @@ -153,7 +151,7 @@ export default class UserService { if (ldapEnabled()) throw new ApiError(HTTPStatus.BadRequest, 'Cannot create a local user, because LDAP authentication is enabled'); - const { roles, ldapOverrideEmail, ...userParams } = params; + const { roles, ...userParams } = params; let user = this.repo.create(userParams); user = await this.repo.save(user); if (roles) { From 3454154cbeac4d703b0bf0d15f0a1305e43b2226 Mon Sep 17 00:00:00 2001 From: Gijsdeman Date: Wed, 26 Feb 2025 13:11:27 +0100 Subject: [PATCH 5/9] refactor: lint entities --- src/entity/Company.ts | 5 ----- src/entity/Contact.ts | 2 -- src/entity/Contract.ts | 5 ----- src/entity/Invoice.ts | 4 ---- src/entity/Product.ts | 4 ---- src/entity/ProductCategory.ts | 1 - src/entity/ProductInstance.ts | 4 ---- src/entity/Role.ts | 1 - src/entity/User.ts | 11 ----------- src/entity/activity/BaseActivity.ts | 1 - src/entity/activity/CompanyActivity.ts | 2 -- src/entity/activity/ContractActivity.ts | 2 -- src/entity/activity/InvoiceActivity.ts | 2 -- src/entity/activity/ProductActivity.ts | 2 -- src/entity/activity/ProductInstanceActivity.ts | 2 -- src/entity/file/CompanyFile.ts | 1 - src/entity/file/ContractFile.ts | 1 - src/entity/file/InvoiceFile.ts | 1 - src/entity/file/ProductFile.ts | 1 - 19 files changed, 52 deletions(-) diff --git a/src/entity/Company.ts b/src/entity/Company.ts index f5635f2..592dbcb 100644 --- a/src/entity/Company.ts +++ b/src/entity/Company.ts @@ -1,14 +1,9 @@ import { Column, Entity, OneToMany } from 'typeorm'; import { BaseEnt } from './BaseEnt'; -// eslint-disable-next-line import/no-cycle import { Contact } from './Contact'; -// eslint-disable-next-line import/no-cycle import { Contract } from './Contract'; -// eslint-disable-next-line import/no-cycle import { Invoice } from './Invoice'; -// eslint-disable-next-line import/no-cycle import { CompanyActivity } from './activity/CompanyActivity'; -// eslint-disable-next-line import/no-cycle import { CompanyFile } from './file/CompanyFile'; import { CompanyStatus } from './enums/CompanyStatus'; diff --git a/src/entity/Contact.ts b/src/entity/Contact.ts index c102bfd..9246aa7 100644 --- a/src/entity/Contact.ts +++ b/src/entity/Contact.ts @@ -1,8 +1,6 @@ import { Column, Entity, JoinColumn, ManyToOne, OneToMany } from 'typeorm'; import { BaseEnt } from './BaseEnt'; -// eslint-disable-next-line import/no-cycle import { Company } from './Company'; -// eslint-disable-next-line import/no-cycle import { Contract } from './Contract'; import { ContactFunction } from './enums/ContactFunction'; import { Gender } from './enums/Gender'; diff --git a/src/entity/Contract.ts b/src/entity/Contract.ts index d7310a9..60e002a 100644 --- a/src/entity/Contract.ts +++ b/src/entity/Contract.ts @@ -1,14 +1,9 @@ import { Column, Entity, JoinTable, JoinColumn, OneToMany, ManyToOne } from 'typeorm'; import { BaseEnt } from './BaseEnt'; -// eslint-disable-next-line import/no-cycle import { Company } from './Company'; -// eslint-disable-next-line import/no-cycle import { Contact } from './Contact'; -// eslint-disable-next-line import/no-cycle import { ContractActivity } from './activity/ContractActivity'; -// eslint-disable-next-line import/no-cycle import { ProductInstance } from './ProductInstance'; -// eslint-disable-next-line import/no-cycle import { ContractFile } from './file/ContractFile'; import { User } from './User'; diff --git a/src/entity/Invoice.ts b/src/entity/Invoice.ts index edce594..f75588a 100644 --- a/src/entity/Invoice.ts +++ b/src/entity/Invoice.ts @@ -1,12 +1,8 @@ import { Column, Entity, ManyToOne, JoinColumn, OneToMany } from 'typeorm'; import { BaseEnt } from './BaseEnt'; -// eslint-disable-next-line import/no-cycle import { Company } from './Company'; -// eslint-disable-next-line import/no-cycle import { ProductInstance } from './ProductInstance'; -// eslint-disable-next-line import/no-cycle import { InvoiceActivity } from './activity/InvoiceActivity'; -// eslint-disable-next-line import/no-cycle import { InvoiceFile } from './file/InvoiceFile'; import { User } from './User'; diff --git a/src/entity/Product.ts b/src/entity/Product.ts index 5850714..390d2e5 100644 --- a/src/entity/Product.ts +++ b/src/entity/Product.ts @@ -1,12 +1,8 @@ import { Column, Entity, JoinColumn, ManyToOne, OneToMany, OneToOne } from 'typeorm'; import { BaseEnt } from './BaseEnt'; -// eslint-disable-next-line import/no-cycle import { ProductInstance } from './ProductInstance'; -// eslint-disable-next-line import/no-cycle import { ProductActivity } from './activity/ProductActivity'; -// eslint-disable-next-line import/no-cycle import { ProductFile } from './file/ProductFile'; -// eslint-disable-next-line import/no-cycle import { ProductCategory } from './ProductCategory'; import { ProductStatus } from './enums/ProductStatus'; import { ProductPricing } from './ProductPricing'; diff --git a/src/entity/ProductCategory.ts b/src/entity/ProductCategory.ts index 91cad3a..964ef1e 100644 --- a/src/entity/ProductCategory.ts +++ b/src/entity/ProductCategory.ts @@ -1,6 +1,5 @@ import { Column, Entity, OneToMany } from 'typeorm'; import { BaseEnt } from './BaseEnt'; -// eslint-disable-next-line import/no-cycle import { Product } from './Product'; @Entity() diff --git a/src/entity/ProductInstance.ts b/src/entity/ProductInstance.ts index 7650672..f6d1b86 100644 --- a/src/entity/ProductInstance.ts +++ b/src/entity/ProductInstance.ts @@ -1,12 +1,8 @@ import { Column, Entity, ManyToOne, JoinColumn, OneToMany } from 'typeorm'; import { BaseEnt } from './BaseEnt'; -// eslint-disable-next-line import/no-cycle import { Contract } from './Contract'; -// eslint-disable-next-line import/no-cycle import { Invoice } from './Invoice'; -// eslint-disable-next-line import/no-cycle import { Product } from './Product'; -// eslint-disable-next-line import/no-cycle import { ProductInstanceActivity } from './activity/ProductInstanceActivity'; @Entity() diff --git a/src/entity/Role.ts b/src/entity/Role.ts index 2e1c9f5..6b3cca8 100644 --- a/src/entity/Role.ts +++ b/src/entity/Role.ts @@ -1,5 +1,4 @@ import { Column, Entity, JoinTable, ManyToMany, PrimaryColumn } from 'typeorm'; -// eslint-disable-next-line import/no-cycle import { User } from './User'; @Entity() diff --git a/src/entity/User.ts b/src/entity/User.ts index 7de6ecf..bd141d8 100644 --- a/src/entity/User.ts +++ b/src/entity/User.ts @@ -1,21 +1,10 @@ import { Column, Entity, JoinTable, ManyToMany, OneToOne } from 'typeorm'; import { BaseEnt } from './BaseEnt'; import { Gender } from './enums/Gender'; -// eslint-disable-next-line import/no-cycle import { Role } from './Role'; import { Roles } from './enums/Roles'; import { IdentityLDAP } from './IdentityLDAP'; import { IdentityLocal } from './IdentityLocal'; -// // eslint-disable-next-line import/no-cycle -// import { CompanyActivity } from './activity/CompanyActivity'; -// // eslint-disable-next-line import/no-cycle -// import { ContractActivity } from './activity/ContractActivity'; -// // eslint-disable-next-line import/no-cycle -// import { InvoiceActivity } from './activity/InvoiceActivity'; -// // eslint-disable-next-line import/no-cycle -// import { ProductActivity } from './activity/ProductActivity'; -// // eslint-disable-next-line import/no-cycle -// import { ProductInstanceActivity } from './activity/ProductInstanceActivity'; @Entity() export class User extends BaseEnt { diff --git a/src/entity/activity/BaseActivity.ts b/src/entity/activity/BaseActivity.ts index ebd2c60..fdfdd80 100644 --- a/src/entity/activity/BaseActivity.ts +++ b/src/entity/activity/BaseActivity.ts @@ -1,5 +1,4 @@ import { Column, JoinColumn, ManyToOne } from 'typeorm'; -// eslint-disable-next-line import/no-cycle import { User } from '../User'; import { BaseEnt } from '../BaseEnt'; import { ActivityType } from '../enums/ActivityType'; diff --git a/src/entity/activity/CompanyActivity.ts b/src/entity/activity/CompanyActivity.ts index 1b27d09..35a2397 100644 --- a/src/entity/activity/CompanyActivity.ts +++ b/src/entity/activity/CompanyActivity.ts @@ -1,6 +1,4 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; -// eslint-disable-next-line import/no-cycle -// eslint-disable-next-line import/no-cycle import { Company } from '../Company'; import { BaseEnt } from '../BaseEnt'; import BaseActivity from './BaseActivity'; diff --git a/src/entity/activity/ContractActivity.ts b/src/entity/activity/ContractActivity.ts index d414dab..fdf6211 100644 --- a/src/entity/activity/ContractActivity.ts +++ b/src/entity/activity/ContractActivity.ts @@ -1,6 +1,4 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; -// eslint-disable-next-line import/no-cycle -// eslint-disable-next-line import/no-cycle import { Contract } from '../Contract'; import { ContractStatus } from '../enums/ContractStatus'; import { BaseEnt } from '../BaseEnt'; diff --git a/src/entity/activity/InvoiceActivity.ts b/src/entity/activity/InvoiceActivity.ts index 678144c..8ca9758 100644 --- a/src/entity/activity/InvoiceActivity.ts +++ b/src/entity/activity/InvoiceActivity.ts @@ -1,6 +1,4 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; -// eslint-disable-next-line import/no-cycle -// eslint-disable-next-line import/no-cycle import { Invoice } from '../Invoice'; import { InvoiceStatus } from '../enums/InvoiceStatus'; import { BaseEnt } from '../BaseEnt'; diff --git a/src/entity/activity/ProductActivity.ts b/src/entity/activity/ProductActivity.ts index 0ca952e..179cee3 100644 --- a/src/entity/activity/ProductActivity.ts +++ b/src/entity/activity/ProductActivity.ts @@ -1,6 +1,4 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; -// eslint-disable-next-line import/no-cycle -// eslint-disable-next-line import/no-cycle import { Product } from '../Product'; import { BaseEnt } from '../BaseEnt'; import BaseActivity from './BaseActivity'; diff --git a/src/entity/activity/ProductInstanceActivity.ts b/src/entity/activity/ProductInstanceActivity.ts index 1c2398f..71577e4 100644 --- a/src/entity/activity/ProductInstanceActivity.ts +++ b/src/entity/activity/ProductInstanceActivity.ts @@ -1,6 +1,4 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; -// eslint-disable-next-line import/no-cycle -// eslint-disable-next-line import/no-cycle import { ProductInstance } from '../ProductInstance'; import { ProductInstanceStatus } from '../enums/ProductActivityStatus'; import { BaseEnt } from '../BaseEnt'; diff --git a/src/entity/file/CompanyFile.ts b/src/entity/file/CompanyFile.ts index 834d2ac..e86060c 100644 --- a/src/entity/file/CompanyFile.ts +++ b/src/entity/file/CompanyFile.ts @@ -1,7 +1,6 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; import { Company } from '../Company'; import BaseFile from './BaseFile'; -// eslint-disable-next-line import/no-cycle @Entity() export class CompanyFile extends BaseFile { diff --git a/src/entity/file/ContractFile.ts b/src/entity/file/ContractFile.ts index 8ea7c29..5796b12 100644 --- a/src/entity/file/ContractFile.ts +++ b/src/entity/file/ContractFile.ts @@ -1,7 +1,6 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; import { Contract } from '../Contract'; import BaseFile from './BaseFile'; -// eslint-disable-next-line import/no-cycle @Entity() export class ContractFile extends BaseFile { diff --git a/src/entity/file/InvoiceFile.ts b/src/entity/file/InvoiceFile.ts index 27b81e9..eb34cbb 100644 --- a/src/entity/file/InvoiceFile.ts +++ b/src/entity/file/InvoiceFile.ts @@ -1,7 +1,6 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; import { Invoice } from '../Invoice'; import BaseFile from './BaseFile'; -// eslint-disable-next-line import/no-cycle @Entity() export class InvoiceFile extends BaseFile { diff --git a/src/entity/file/ProductFile.ts b/src/entity/file/ProductFile.ts index 432550f..e26569b 100644 --- a/src/entity/file/ProductFile.ts +++ b/src/entity/file/ProductFile.ts @@ -1,7 +1,6 @@ import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; import { Product } from '../Product'; import BaseFile from './BaseFile'; -// eslint-disable-next-line import/no-cycle @Entity() export class ProductFile extends BaseFile { From d9ac9390974acf85e838f2ec05846225b0a77332 Mon Sep 17 00:00:00 2001 From: Gijsdeman Date: Wed, 26 Feb 2025 13:31:11 +0100 Subject: [PATCH 6/9] refactor: lint services --- src/helpers/activity.ts | 2 ++ src/helpers/currency.ts | 2 +- src/helpers/entityChanges.ts | 14 +++++++++----- src/helpers/fileHelper.ts | 8 ++++---- src/helpers/filters.ts | 3 ++- src/helpers/mailBuilder.ts | 2 -- src/helpers/rawQueries.ts | 2 ++ src/helpers/validation.ts | 22 ++++++++++++++-------- 8 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/helpers/activity.ts b/src/helpers/activity.ts index 9517c67..a060724 100644 --- a/src/helpers/activity.ts +++ b/src/helpers/activity.ts @@ -1,3 +1,5 @@ +/* eslint-disable */ +// TODO this file needs a bigger overhaul for proper linting import _ from 'lodash'; import { Repository } from 'typeorm'; import { User } from '../entity/User'; diff --git a/src/helpers/currency.ts b/src/helpers/currency.ts index 9467ee0..db23da6 100644 --- a/src/helpers/currency.ts +++ b/src/helpers/currency.ts @@ -11,7 +11,7 @@ export default class Currency { locale = 'nl-NL'; break; default: - throw new TypeError(`Unknown language: ${language}`); + throw new TypeError(`Unknown language: ${language as string}`); } return new Intl.NumberFormat(locale, { maximumFractionDigits: 2, minimumFractionDigits: 2 }).format(price / 100); diff --git a/src/helpers/entityChanges.ts b/src/helpers/entityChanges.ts index 9db2ac3..b1fb115 100644 --- a/src/helpers/entityChanges.ts +++ b/src/helpers/entityChanges.ts @@ -6,12 +6,16 @@ export default function getEntityChanges(newEntity: Partial, oldEntity: T): Partial { const result: Partial = {}; - Object.keys(newEntity).forEach((k) => { - // @ts-ignore - if (!(newEntity[k] instanceof Date && newEntity[k].getTime() === oldEntity[k].getTime())) { - // @ts-ignore + Object.keys(newEntity).forEach((key) => { + const k = key as keyof T; + if ( + !( + newEntity[k] instanceof Date && + oldEntity[k] instanceof Date && + newEntity[k].getTime() === oldEntity[k].getTime() + ) + ) { if (newEntity[k] !== oldEntity[k]) { - // @ts-ignore result[k] = newEntity[k]; } } diff --git a/src/helpers/fileHelper.ts b/src/helpers/fileHelper.ts index b6b6f00..c2650b7 100644 --- a/src/helpers/fileHelper.ts +++ b/src/helpers/fileHelper.ts @@ -57,8 +57,8 @@ export default class FileHelper { public static removeFile(file: BaseFile) { try { fs.unlinkSync(file.location); - } catch (e) { - console.log(`File ${file.name} at ${file.location} does not exist, so could not be removed`); + } catch { + console.warn(`File ${file.name} at ${file.location} does not exist, so could not be removed`); } } @@ -69,8 +69,8 @@ export default class FileHelper { public static removeFileAtLoc(location: string) { try { fs.unlinkSync(location); - } catch (e) { - console.log(`File ${location} does not exist, so could not be removed`); + } catch { + console.warn(`File ${location} does not exist, so could not be removed`); } } } diff --git a/src/helpers/filters.ts b/src/helpers/filters.ts index a1bbb62..9b0b3a8 100644 --- a/src/helpers/filters.ts +++ b/src/helpers/filters.ts @@ -1,3 +1,5 @@ +/* eslint-disable */ +// TODO Check if needs to be refactored import { Brackets, FindOptionsWhere, ILike, In, SelectQueryBuilder } from 'typeorm'; import { BaseEnt } from '../entity/BaseEnt'; import { ListOrFilter, ListParams } from '../controllers/ListParams'; @@ -45,7 +47,6 @@ export function addQuerySearch(fieldNames: string[], search?: temp2[intermediates[i]] = temp; temp = temp2; } - console.log(temp); return temp; }), ); diff --git a/src/helpers/mailBuilder.ts b/src/helpers/mailBuilder.ts index 35ebac3..d8d4323 100644 --- a/src/helpers/mailBuilder.ts +++ b/src/helpers/mailBuilder.ts @@ -1,6 +1,4 @@ -// eslint-disable-next-line import/no-cycle import UserService from '../services/UserService'; -// eslint-disable-next-line import/no-cycle import InvoiceService from '../services/InvoiceService'; import { Roles } from '../entity/enums/Roles'; import { Mailer } from '../mailer/Mailer'; diff --git a/src/helpers/rawQueries.ts b/src/helpers/rawQueries.ts index b05cc23..a97ac61 100644 --- a/src/helpers/rawQueries.ts +++ b/src/helpers/rawQueries.ts @@ -1,3 +1,5 @@ +/* eslint-disable */ +// TODO rewrite to typeorm queries import { ListParams } from '../controllers/ListParams'; import { ActivityType } from '../entity/enums/ActivityType'; import { ContractStatus } from '../entity/enums/ContractStatus'; diff --git a/src/helpers/validation.ts b/src/helpers/validation.ts index 93b9628..1943d3c 100644 --- a/src/helpers/validation.ts +++ b/src/helpers/validation.ts @@ -25,7 +25,6 @@ export const validate = async (validations: ValidationChain[], req: express.Requ */ export const validateSeq = async (validations: ValidationChain[], req: express.Request) => { for (let i = 0; i < validations.length; i++) { - // eslint-disable-next-line no-await-in-loop const result = await validations[i].run(req); if (!result.isEmpty()) break; } @@ -41,13 +40,20 @@ export const validateSeq = async (validations: ValidationChain[], req: express.R * @param contactId ID of the contact to check * @param req Express.js request object, with the company id in the body */ -export const contactInCompany = async (contactId: number, req: express.Request) => { - new ContactService().getContact(contactId).then((contact) => { - if (contact.companyId !== req.body.companyId) { - return Promise.reject(new Error('Contact does not belong to company')); - } - return Promise.resolve(); - }); +export const contactInCompany = (contactId: number, req: express.Request) => { + new ContactService() + .getContact(contactId) + .then((contact) => { + // TODO how to type body of request? + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (contact.companyId !== req.body.companyId) { + return Promise.reject(new Error('Contact does not belong to company')); + } + return Promise.resolve(); + }) + .catch((err: Error) => { + return Promise.reject(new ApiError(HTTPStatus.BadRequest, err.message)); + }); }; /** From 478f7c9e41b2b167b662366ca98f2359002308ae Mon Sep 17 00:00:00 2001 From: Gijsdeman Date: Wed, 26 Feb 2025 13:41:10 +0100 Subject: [PATCH 7/9] refactor: lint dbvalidator --- src/dbvalidator/GEWISrecipient.ts | 9 +- src/dbvalidator/contracts.ts | 36 ++--- src/dbvalidator/invoices.ts | 8 +- src/dbvalidator/productInstances.ts | 8 +- src/dbvalidator/validate.ts | 28 ++-- src/index.ts | 141 ++++++++++---------- src/mailer/Mailer.ts | 10 +- src/migration/1627468331061-Localization.ts | 2 +- src/types.d.ts | 8 ++ 9 files changed, 135 insertions(+), 115 deletions(-) create mode 100644 src/types.d.ts diff --git a/src/dbvalidator/GEWISrecipient.ts b/src/dbvalidator/GEWISrecipient.ts index 254a029..4cc7185 100644 --- a/src/dbvalidator/GEWISrecipient.ts +++ b/src/dbvalidator/GEWISrecipient.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-param-reassign */ import { Product } from '../entity/Product'; import replaceAll from '../helpers/replaceAll'; import AppDataSource from '../database'; @@ -11,7 +10,7 @@ export async function replaceGEWISRecipient() { let count = 0; const productRepo = AppDataSource.getRepository(Product); const products = await productRepo.find(); - products.forEach((p) => { + for (const p of products) { if ( p.description.includes('{instelling}') || p.contractTextDutch.includes('{instelling}') || @@ -37,10 +36,10 @@ export async function replaceGEWISRecipient() { '\\GEWISRecipient\\xspace', ); - p.save(); - }); + await p.save(); + } - console.log( + console.warn( `The following products had one or multiple instances of {instelling} replaced (${count}): ${logResult.substr(0, logResult.length - 2)}`, ); } diff --git a/src/dbvalidator/contracts.ts b/src/dbvalidator/contracts.ts index f4cc9bb..f360952 100644 --- a/src/dbvalidator/contracts.ts +++ b/src/dbvalidator/contracts.ts @@ -18,10 +18,10 @@ export async function allContractsAreCreated() { const activityRepo = AppDataSource.getRepository(ContractActivity); const contracts = await contractRepo.find({ relations: ['activities'] }); - contracts.forEach((c) => { + for (const c of contracts) { const createdStatus = c.activities.find((a) => a.subType === ContractStatus.CREATED); if (createdStatus === undefined) { - activityRepo.save({ + await activityRepo.save({ createdAt: new Date(c.createdAt.getDate() - 1), updatedAt: new Date(), createdById: c.createdById, @@ -35,10 +35,10 @@ export async function allContractsAreCreated() { logResult += `C${c.id}, `; count++; } - }); + } - console.log( - `The following contracts did not have a 'CREATED' status (${count}): ${logResult.substr(0, logResult.length - 2)}`, + console.warn( + `The following contracts did not have a 'CREATED' status (${count}): ${logResult.substring(0, logResult.length - 2)}`, ); } @@ -53,15 +53,15 @@ export async function allProductsAreCancelledIfContractIsCancelled() { const productInstanceActivityRepo = AppDataSource.getRepository(ProductInstanceActivity); const contracts = await contractRepo.find({ relations: ['products', 'products.activities', 'activities'] }); - contracts.forEach((c) => { + for (const c of contracts) { const cancelledActivity = c.activities.find((a) => a.subType === ContractStatus.CANCELLED); if (cancelledActivity) { - c.products.forEach((p) => { + for (const p of c.products) { const index = p.activities.find((a) => a.subType === ProductInstanceStatus.CANCELLED); if (index === undefined) { - productInstanceActivityRepo.save({ + await productInstanceActivityRepo.save({ createdAt: cancelledActivity.createdAt, updatedAt: new Date(), productInstanceId: p.id, @@ -75,12 +75,12 @@ export async function allProductsAreCancelledIfContractIsCancelled() { logResult += `C${c.id} (P${p.id}), `; count++; } - }); + } } - }); + } - console.log( - `The following cancelled contracts had non-cancelled products (${count}): ${logResult.substr(0, logResult.length - 2)}`, + console.warn( + `The following cancelled contracts had non-cancelled products (${count}): ${logResult.substring(0, logResult.length - 2)}`, ); } @@ -95,17 +95,17 @@ export async function allProductsAreDeliveredIfContractIsFinished() { const productInstanceActivityRepo = AppDataSource.getRepository(ProductInstanceActivity); const contracts = await contractRepo.find({ relations: ['products', 'products.activities', 'activities'] }); - contracts.forEach((c) => { + for (const c of contracts) { const finishedActivity = c.activities.find((a) => a.subType === ContractStatus.FINISHED); if (finishedActivity) { - c.products.forEach((p) => { + for (const p of c.products) { const index = p.activities.find( (a) => a.subType === ProductInstanceStatus.CANCELLED || a.subType === ProductInstanceStatus.DELIVERED, ); if (index === undefined) { - productInstanceActivityRepo.save({ + await productInstanceActivityRepo.save({ createdAt: finishedActivity.createdAt, updatedAt: new Date(), productInstanceId: p.id, @@ -119,11 +119,11 @@ export async function allProductsAreDeliveredIfContractIsFinished() { logResult += `C${c.id} (P${p.id}), `; count++; } - }); + } } - }); + } - console.log( + console.warn( `The following contracts were finished, but did not have delivered/cancelled products (${count}): ${logResult.substr(0, logResult.length - 2)}`, ); } diff --git a/src/dbvalidator/invoices.ts b/src/dbvalidator/invoices.ts index 35bf5cc..f439f10 100644 --- a/src/dbvalidator/invoices.ts +++ b/src/dbvalidator/invoices.ts @@ -14,10 +14,10 @@ export async function allInvoicesAreCreated() { const activityRepo = AppDataSource.getRepository(InvoiceActivity); const invoices = await invoiceRepo.find({ relations: ['activities'] }); - invoices.forEach((i) => { + for (const i of invoices) { const createdStatus = i.activities.find((a) => a.subType === InvoiceStatus.CREATED); if (createdStatus === undefined) { - activityRepo.save({ + await activityRepo.save({ createdAt: new Date(i.createdAt.getDate() - 1), updatedAt: new Date(), createdById: i.createdById, @@ -31,9 +31,9 @@ export async function allInvoicesAreCreated() { logResult += `F${i.id}, `; count++; } - }); + } - console.log( + console.warn( `The following invoices did not have a 'CREATED' status (${count}): ${logResult.substr(0, logResult.length - 2)}`, ); } diff --git a/src/dbvalidator/productInstances.ts b/src/dbvalidator/productInstances.ts index 4968d22..fbf5914 100644 --- a/src/dbvalidator/productInstances.ts +++ b/src/dbvalidator/productInstances.ts @@ -14,10 +14,10 @@ export async function allProductInstancesWereNotDelivered() { const activityRepo = AppDataSource.getRepository(ProductInstanceActivity); const productInstances = await productRepo.find({ relations: ['activities', 'contract'] }); - productInstances.forEach((p) => { + for (const p of productInstances) { const notDeliveredStatus = p.activities.find((a) => a.subType === ProductInstanceStatus.NOTDELIVERED); if (notDeliveredStatus === undefined) { - activityRepo.save({ + await activityRepo.save({ createdAt: new Date(p.createdAt.getDate() - 1), updatedAt: new Date(), productInstanceId: p.id, @@ -31,9 +31,9 @@ export async function allProductInstancesWereNotDelivered() { logResult += `C${p.contractId} (P${p.id}), `; count++; } - }); + } - console.log( + console.warn( `The following contracts had products that do not have a 'NOTDELIVERED' status (${count}): ${logResult.substr(0, logResult.length - 2)}`, ); } diff --git a/src/dbvalidator/validate.ts b/src/dbvalidator/validate.ts index efc668c..6d89f47 100644 --- a/src/dbvalidator/validate.ts +++ b/src/dbvalidator/validate.ts @@ -11,16 +11,18 @@ import { replaceGEWISRecipient } from './GEWISrecipient'; dotenv.config({ path: '.env' }); -AppDataSource.initialize().then(async () => { - const t1 = new Date(); - console.log('Start database validation...'); - await Promise.all([ - allContractsAreCreated(), - allInvoicesAreCreated(), - allProductInstancesWereNotDelivered(), - allProductsAreCancelledIfContractIsCancelled(), - allProductsAreDeliveredIfContractIsFinished(), - replaceGEWISRecipient(), - ]); - console.log(`Database validated in ${new Date().getTime() - t1.getTime()}ms`); -}); +AppDataSource.initialize() + .then(async () => { + const t1 = new Date(); + console.warn('Start database validation...'); + await Promise.all([ + allContractsAreCreated(), + allInvoicesAreCreated(), + allProductInstancesWereNotDelivered(), + allProductsAreCancelledIfContractIsCancelled(), + allProductsAreDeliveredIfContractIsFinished(), + replaceGEWISRecipient(), + ]); + console.warn(`Database validated in ${new Date().getTime() - t1.getTime()}ms`); + }) + .catch((e) => console.error(e)); diff --git a/src/index.ts b/src/index.ts index dcec251..e621e7e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,6 +11,7 @@ import bodyParser from 'body-parser'; import session from 'express-session'; import { TypeormStore } from 'connect-typeorm'; import passport from 'passport'; +import { DataSource } from 'typeorm'; import swaggerDocument from '../build/swagger.json'; import { RegisterRoutes } from '../build/routes'; import startEvents from './timedevents/cron'; @@ -29,7 +30,6 @@ import { User } from './entity/User'; import UserService from './services/UserService'; import { ldapLogin, LDAPStrategy } from './auth'; import AppDataSource from './database'; -import { DataSource } from 'typeorm'; dotenv.config({ path: '.env' }); @@ -65,84 +65,91 @@ export function setupSessionSupport(dataSource: DataSource, app: Express) { // config(); } -AppDataSource.initialize().then(async (dataSource) => { - // Setup of database - await new UserService().setupRoles(); +AppDataSource.initialize() + .then(async (dataSource) => { + // Setup of database + await new UserService().setupRoles(); - const app = express(); + const app = express(); - app.use(express.json({ limit: '50mb' })); - app.use(bodyParser.urlencoded({ extended: false, limit: '50mb' })); + app.use(express.json({ limit: '50mb' })); + app.use(bodyParser.urlencoded({ extended: false, limit: '50mb' })); - app.set('trust proxy', 2); + app.set('trust proxy', 2); - setupSessionSupport(dataSource, app); + setupSessionSupport(dataSource, app); - passport.serializeUser((user: any, done) => { - done(null, user.id); - }); + passport.serializeUser((user, done) => { + done(null, user.id); + }); - passport.deserializeUser(async (id: number, done) => { - const userRepo = dataSource.getRepository(User); - const user = await userRepo.findOne({ where: { id }, relations: ['roles'] }); - if (user === undefined) { - return done(null, false); - } - return done(null, user); - }); + // eslint-disable-next-line @typescript-eslint/no-misused-promises -- async is allowed here + passport.deserializeUser(async (id: number, done) => { + try { + const userRepo = dataSource.getRepository(User); + const user = await userRepo.findOne({ where: { id }, relations: ['roles'] }); + if (user === undefined) { + done(null, false); + } + done(null, user); + } catch (err) { + done(err); + } + }); - passport.use(LDAPStrategy); - passport.use(localStrategy); + passport.use(LDAPStrategy); + passport.use(localStrategy); - app.post('/api/login/ldap', ldapLogin); - app.post('/api/login/local', localLogin); + app.post('/api/login/ldap', ldapLogin); + app.post('/api/login/local', localLogin); - RegisterRoutes(app); + RegisterRoutes(app); - app.use(methodOverride()); + app.use(methodOverride()); - // Create file generation folders - if (!fs.existsSync(path.join(__dirname, '/../tmp'))) { - fs.mkdirSync(path.join(__dirname, '/../tmp')); - } - if (!fs.existsSync(path.join(__dirname, '/../data/generated'))) { - // Recursive so data is also created - fs.mkdirSync(path.join(__dirname, '/../data/generated'), { recursive: true }); - } - if (!fs.existsSync(path.join(__dirname, '/../data/uploads'))) { - fs.mkdirSync(path.join(__dirname, '/../data/uploads')); - } - if (!fs.existsSync(path.join(__dirname, '/../data/logos'))) { - fs.mkdirSync(path.join(__dirname, '/../data/logos')); - } - if (!fs.existsSync(path.join(__dirname, '/../data/backgrounds'))) { - fs.mkdirSync(path.join(__dirname, '/../data/backgrounds')); - } + // Create file generation folders + if (!fs.existsSync(path.join(__dirname, '/../tmp'))) { + fs.mkdirSync(path.join(__dirname, '/../tmp')); + } + if (!fs.existsSync(path.join(__dirname, '/../data/generated'))) { + // Recursive so data is also created + fs.mkdirSync(path.join(__dirname, '/../data/generated'), { recursive: true }); + } + if (!fs.existsSync(path.join(__dirname, '/../data/uploads'))) { + fs.mkdirSync(path.join(__dirname, '/../data/uploads')); + } + if (!fs.existsSync(path.join(__dirname, '/../data/logos'))) { + fs.mkdirSync(path.join(__dirname, '/../data/logos')); + } + if (!fs.existsSync(path.join(__dirname, '/../data/backgrounds'))) { + fs.mkdirSync(path.join(__dirname, '/../data/backgrounds')); + } - // Give additional error information when in development mode. - app.use( - errorhandler({ - debug: process.env.NODE_ENV === 'development', - safeFields: ['message'], - }), - ); - - // If env file specifies development, use swagger UI - if (process.env.NODE_ENV === 'development') { - app.use('/api/swagger-ui', swaggerUi.serve, swaggerUi.setup(swaggerDocument)); - app.get('/api/swagger.json', (req, res) => { - res.sendFile(path.join(__dirname, './public/swagger.json')); - }); - } + // Give additional error information when in development mode. + app.use( + errorhandler({ + debug: process.env.NODE_ENV === 'development', + safeFields: ['message'], + }), + ); + + // If env file specifies development, use swagger UI + if (process.env.NODE_ENV === 'development') { + app.use('/api/swagger-ui', swaggerUi.serve, swaggerUi.setup(swaggerDocument)); + app.get('/api/swagger.json', (req, res) => { + res.sendFile(path.join(__dirname, './public/swagger.json')); + }); + } - app.use('/static/logos', express.static(path.join(__dirname, '../data/logos'))); - app.use('/static/backgrounds', express.static(path.join(__dirname, '../data/backgrounds'))); + app.use('/static/logos', express.static(path.join(__dirname, '../data/logos'))); + app.use('/static/backgrounds', express.static(path.join(__dirname, '../data/backgrounds'))); - // Announce port that is listened to in the console - app.listen(PORT, () => { - console.log(`Server is listening on port ${PORT}`); - }); + // Announce port that is listened to in the console + app.listen(PORT, () => { + console.warn(`Server is listening on port ${PORT}`); + }); - // Enable timed events - startEvents(); -}); + // Enable timed events + startEvents(); + }) + .catch((e) => console.error(e)); diff --git a/src/mailer/Mailer.ts b/src/mailer/Mailer.ts index 5ef5b2c..0b0ca45 100644 --- a/src/mailer/Mailer.ts +++ b/src/mailer/Mailer.ts @@ -1,6 +1,10 @@ import Mail from 'nodemailer/lib/mailer'; import { createTransporter } from './transporter'; +interface SentMessageInfo { + messageId: string; +} + /** * Singleton class to handle all mail-related operations */ @@ -22,10 +26,10 @@ export class Mailer { async send(mail: Mail.Options) { try { - const info = await this.transporter.sendMail(mail); - console.log('Message sent: %s', info.messageId); + const info = (await this.transporter.sendMail(mail)) as SentMessageInfo; + console.warn('Message sent: %s', info.messageId); } catch (e) { - console.log(e); + console.error(e); } } } diff --git a/src/migration/1627468331061-Localization.ts b/src/migration/1627468331061-Localization.ts index 0f5525d..a451cd0 100644 --- a/src/migration/1627468331061-Localization.ts +++ b/src/migration/1627468331061-Localization.ts @@ -4,7 +4,7 @@ import replaceAll from '../helpers/replaceAll'; export class Localization1627468331061 implements MigrationInterface { name = 'Localization1627468331061'; - private async query(queryRunner: QueryRunner, query: string): Promise { + private async query(queryRunner: QueryRunner, query: string): Promise { if (process.env.TYPEORM_CONNECTION === 'postgres') { return queryRunner.query(replaceAll(query, '`', '"')); } diff --git a/src/types.d.ts b/src/types.d.ts new file mode 100644 index 0000000..0104aac --- /dev/null +++ b/src/types.d.ts @@ -0,0 +1,8 @@ +import { User as EntityUser } from './entity/User'; + +declare global { + namespace Express { + // eslint-disable-next-line @typescript-eslint/no-empty-object-type + interface User extends EntityUser {} + } +} From bdcacc72cc8fde6002c66792aba0e945fc1ac497 Mon Sep 17 00:00:00 2001 From: Gijsdeman Date: Wed, 26 Feb 2025 16:28:53 +0100 Subject: [PATCH 8/9] refactor: lint controllers --- src/auth/LDAPStrategy.ts | 9 ++-- src/auth/LocalStrategy.ts | 3 +- src/auth/authentication.ts | 6 +-- src/controllers/CompanyController.ts | 24 ++++----- src/controllers/ContactController.ts | 10 ++-- src/controllers/ContractController.ts | 57 ++++++++++---------- src/controllers/InvoiceController.ts | 36 ++++++------- src/controllers/ListParams.ts | 2 +- src/controllers/ProductCategoryController.ts | 8 +-- src/controllers/ProductController.ts | 28 +++++----- src/controllers/RootController.ts | 18 +++---- src/controllers/UserController.ts | 32 +++++------ src/controllers/VATController.ts | 6 +-- src/helpers/validation.ts | 16 +++--- src/services/AuthService.ts | 16 +++--- src/services/FileService.ts | 12 ++--- src/types.d.ts | 15 ++++++ 17 files changed, 156 insertions(+), 142 deletions(-) diff --git a/src/auth/LDAPStrategy.ts b/src/auth/LDAPStrategy.ts index e18af03..491ff71 100644 --- a/src/auth/LDAPStrategy.ts +++ b/src/auth/LDAPStrategy.ts @@ -8,6 +8,7 @@ import { Role } from '../entity/Role'; import UserService from '../services/UserService'; import { Roles } from '../entity/enums/Roles'; import AppDataSource from '../database'; +import { ExpressRequest } from '../types'; const isDefined = (i: string | undefined) => i !== undefined && i !== ''; @@ -44,16 +45,16 @@ export const updateUserInformation = async (user: User, ldapUser: any): Promise< await new UserService().assignRoles(user, userRoles); const identity = user.identityLdap; - // eslint-disable-next-line no-param-reassign + if (identity && !identity.overrideEmail) user.email = ldapUser.mail; - // eslint-disable-next-line no-param-reassign + user.firstName = ldapUser.givenName; - // eslint-disable-next-line no-param-reassign + user.lastName = ldapUser.sn; return user.save(); }; -export const ldapLogin = (req: express.Request, res: express.Response, next: express.NextFunction) => { +export const ldapLogin = (req: ExpressRequest, res: express.Response, next: express.NextFunction) => { passport.authenticate('ldapauth', async (err: any, ldapUser: any, info: any) => { if (err) { return next(err); diff --git a/src/auth/LocalStrategy.ts b/src/auth/LocalStrategy.ts index e348564..55c0556 100644 --- a/src/auth/LocalStrategy.ts +++ b/src/auth/LocalStrategy.ts @@ -7,6 +7,7 @@ import { IdentityLocal } from '../entity/IdentityLocal'; import { User } from '../entity/User'; import { ApiError, HTTPStatus } from '../helpers/error'; import AppDataSource from '../database'; +import { ExpressRequest } from '../types'; const INVALID_LOGIN = 'Invalid email or password.'; const VERIFY_ACCOUNT = 'Please verify your account and set your password with the link received by email.'; @@ -67,7 +68,7 @@ export default new LocalStrategy( }, ); -export const localLogin = (req: express.Request, res: express.Response, next: express.NextFunction) => { +export const localLogin = (req: ExpressRequest, res: express.Response, next: express.NextFunction) => { passport.authenticate('local', (err: any, user: any) => { if (err) { return next(err); diff --git a/src/auth/authentication.ts b/src/auth/authentication.ts index 0649bd7..c8683d3 100644 --- a/src/auth/authentication.ts +++ b/src/auth/authentication.ts @@ -1,8 +1,8 @@ -import express from 'express'; import { IdentityApiKey } from '../entity/IdentityApiKey'; import { User } from '../entity/User'; import { ApiError, HTTPStatus } from '../helpers/error'; import AppDataSource from '../database'; +import { ExpressRequest } from '../types'; async function authWithApiKey(apiKey: string) { const split = apiKey.split(' '); @@ -22,10 +22,10 @@ async function authWithApiKey(apiKey: string) { } export async function expressAuthentication( - request: express.Request, + request: ExpressRequest, securityName: string, scopes?: string[], -): Promise { +): Promise { switch (securityName) { case 'local': { const auth = request.header('Authentication'); diff --git a/src/controllers/CompanyController.ts b/src/controllers/CompanyController.ts index 43e0bf7..af31868 100644 --- a/src/controllers/CompanyController.ts +++ b/src/controllers/CompanyController.ts @@ -1,4 +1,4 @@ -import express from 'express'; +import fs from 'fs'; import { body } from 'express-validator'; import { Company } from '../entity/Company'; import { Invoice } from '../entity/Invoice'; @@ -24,13 +24,14 @@ import BaseFile from '../entity/file/BaseFile'; import { CompanyFile } from '../entity/file/CompanyFile'; import StatisticsService, { ContractedProductsAnalysis } from '../services/StatisticsService'; import { Roles } from '../entity/enums/Roles'; +import { ExpressRequest } from '../types'; import { ListParams } from './ListParams'; import { Body, Tags, Controller, Post, Route, Put, Get, Security, Response, Delete, Request } from 'tsoa'; @Route('company') @Tags('Company') export class CompanyController extends Controller { - private async validateCompanyParams(req: express.Request): Promise { + private async validateCompanyParams(req: ExpressRequest): Promise { await validate( [ body('name').notEmpty().trim(), @@ -103,7 +104,7 @@ export class CompanyController extends Controller { @Post() @Security('local', ['ADMIN']) @Response(401) - public async createCompany(@Body() params: CompanyParams, @Request() req: express.Request): Promise { + public async createCompany(@Body() params: CompanyParams, @Request() req: ExpressRequest): Promise { await this.validateCompanyParams(req); return new CompanyService().createCompany(params); } @@ -120,7 +121,7 @@ export class CompanyController extends Controller { public async updateCompany( id: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await this.validateCompanyParams(req); return new CompanyService({ actor: req.user as User }).updateCompany(id, params); @@ -129,7 +130,6 @@ export class CompanyController extends Controller { /** * Delete company * @param id ID of the company to delete - * @param req Express.js request object */ @Delete('{id}') @Security('local', ['ADMIN']) @@ -146,7 +146,7 @@ export class CompanyController extends Controller { @Put('{id}/logo') @Security('local', ['GENERAL', 'ADMIN']) @Response(401) - public async uploadCompanyLogo(@Request() req: express.Request, id: number) { + public async uploadCompanyLogo(@Request() req: ExpressRequest, id: number) { await FileService.uploadCompanyLogo(req, id); } @@ -198,7 +198,7 @@ export class CompanyController extends Controller { @Post('{id}/file/upload') @Security('local', ['GENERAL', 'ADMIN']) @Response(401) - public async uploadCompanyFile(id: number, @Request() req: express.Request): Promise { + public async uploadCompanyFile(id: number, @Request() req: ExpressRequest): Promise { const actor = req.user as User; if (req.body.createdAt !== undefined && !actor.hasRole(Roles.ADMIN)) { throw new ApiError( @@ -207,7 +207,7 @@ export class CompanyController extends Controller { ); } - return new FileService(CompanyFile, { actor: req.user as User }).uploadFile(req, id); + return (await new FileService(CompanyFile, { actor: req.user as User }).uploadFile(req, id)) as CompanyFile; } /** @@ -219,7 +219,7 @@ export class CompanyController extends Controller { @Get('{id}/file/{fileId}') @Security('local', ['GENERAL', 'ADMIN']) @Response(401) - public async getCompanyFile(id: number, fileId: number): Promise { + public async getCompanyFile(id: number, fileId: number): Promise { const file = await new FileService(CompanyFile).getFile(id, fileId); return FileHelper.putFileInResponse(this, file); @@ -239,7 +239,7 @@ export class CompanyController extends Controller { id: number, fileId: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateFileParams(req); return new FileService(CompanyFile).updateFile(id, fileId, params); @@ -269,7 +269,7 @@ export class CompanyController extends Controller { public async addCompanyComment( id: number, @Body() params: ActivityParams, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateCommentParams(req); const p: FullActivityParams = { @@ -294,7 +294,7 @@ export class CompanyController extends Controller { id: number, activityId: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateActivityParams(req); const p: Partial = { diff --git a/src/controllers/ContactController.ts b/src/controllers/ContactController.ts index 63c4b47..23860eb 100644 --- a/src/controllers/ContactController.ts +++ b/src/controllers/ContactController.ts @@ -1,18 +1,18 @@ import { body } from 'express-validator'; -import express from 'express'; import { Contact } from '../entity/Contact'; import { WrappedApiError } from '../helpers/error'; import ContactService, { ContactListResponse, ContactParams, ContactSummary } from '../services/ContactService'; import { validate } from '../helpers/validation'; import { Gender } from '../entity/enums/Gender'; import { ContactFunction } from '../entity/enums/ContactFunction'; +import { ExpressRequest } from '../types'; import { ListParams } from './ListParams'; import { Body, Controller, Post, Route, Put, Tags, Get, Security, Response, Request, Delete } from 'tsoa'; @Route('contact') @Tags('Contact') export class ContactController extends Controller { - private async validateContactParams(req: express.Request) { + private async validateContactParams(req: ExpressRequest) { const emailOptionalFunctions = [ ContactFunction.SIGNATORY_AUTHORIZED, ContactFunction.ASSISTING, @@ -80,7 +80,7 @@ export class ContactController extends Controller { @Post() @Security('local', ['GENERAL', 'ADMIN']) @Response(401) - public async createContact(@Body() params: ContactParams, @Request() req: express.Request): Promise { + public async createContact(@Body() params: ContactParams, @Request() req: ExpressRequest): Promise { await this.validateContactParams(req); return new ContactService().createContact(params); } @@ -89,7 +89,7 @@ export class ContactController extends Controller { * updateContact() - update contact * @param id ID of contact to update * @param params Update subset of parameter of contact - * @param req: express.Request + * @param req: ExpressRequest */ @Put('{id}') @Security('local', ['GENERAL', 'ADMIN']) @@ -97,7 +97,7 @@ export class ContactController extends Controller { public async updateContact( id: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await this.validateContactParams(req); return new ContactService().updateContact(id, params); diff --git a/src/controllers/ContractController.ts b/src/controllers/ContractController.ts index e216171..9fb8450 100644 --- a/src/controllers/ContractController.ts +++ b/src/controllers/ContractController.ts @@ -1,4 +1,4 @@ -import express from 'express'; +import fs from 'fs'; import { body } from 'express-validator'; import { Contract } from '../entity/Contract'; import ContractService, { ContractListResponse, ContractParams } from '../services/ContractService'; @@ -29,24 +29,24 @@ import { Language } from '../entity/enums/Language'; import { RecentContract } from '../helpers/rawQueries'; import { ContractSummary } from '../entity/Summaries'; import { Roles } from '../entity/enums/Roles'; +import { ExpressRequest } from '../types'; import { ListParams } from './ListParams'; import { Body, Controller, Delete, Get, Post, Put, Request, Response, Route, Security, Tags } from 'tsoa'; @Route('contract') @Tags('Contract') export class ContractController extends Controller { - private async validateContractParams(req: express.Request) { + private async validateContractParams(req: ExpressRequest) { await validate( [ body('title').notEmpty().trim(), body('companyId').isInt(), - body('contactId').custom((contactId) => { - return new ContactService().getContact(contactId).then((contact) => { - if (contact.companyId !== req.body.companyId) { - return Promise.reject(new Error('Contact does not belong to company')); - } - return Promise.resolve(); - }); + body('contactId').custom(async (contactId: number) => { + const contact = await new ContactService().getContact(contactId); + if (contact.companyId !== req.body.companyId) { + return Promise.reject(new Error('Contact does not belong to company')); + } + return await Promise.resolve(); }), body('comments').optional({ checkFalsy: true }).isString().trim(), body('assignedToId').optional({ checkFalsy: true }).isInt(), @@ -55,7 +55,7 @@ export class ContractController extends Controller { ); } - private async validateProductInstanceParams(req: express.Request) { + private async validateProductInstanceParams(req: ExpressRequest) { await validate( [ body('productId').isInt(), @@ -96,7 +96,7 @@ export class ContractController extends Controller { @Get('recent') @Security('local', ['SIGNEE', 'FINANCIAL', 'GENERAL', 'ADMIN', 'AUDIT']) @Response(401) - public async getRecentContracts(@Request() req: express.Request): Promise { + public async getRecentContracts(@Request() req: ExpressRequest): Promise { return new ContractService().getRecentContracts(req.user! as User); } @@ -119,7 +119,7 @@ export class ContractController extends Controller { @Post() @Security('local', ['GENERAL', 'ADMIN']) @Response(401) - public async createContract(@Request() req: express.Request, @Body() params: ContractParams): Promise { + public async createContract(@Request() req: ExpressRequest, @Body() params: ContractParams): Promise { await this.validateContractParams(req); return new ContractService({ actor: req.user as User }).createContract(params); } @@ -136,7 +136,7 @@ export class ContractController extends Controller { public async updateContract( id: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await this.validateContractParams(req); return new ContractService({ actor: req.user as User }).updateContract(id, params); @@ -145,7 +145,6 @@ export class ContractController extends Controller { /** * Delete a contract, if it has no products or updated statuses * @param id ID of the contract - * @param req Express.js request object */ @Delete('{id}') @Security('local', ['GENERAL', 'ADMIN']) @@ -166,7 +165,7 @@ export class ContractController extends Controller { public async addProductInstanceToContract( id: number, @Body() params: ProductInstanceParams, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await this.validateProductInstanceParams(req); return new ProductInstanceService({ actor: req.user as User }).addProduct(id, params); @@ -186,7 +185,7 @@ export class ContractController extends Controller { id: number, prodId: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await this.validateProductInstanceParams(req); return new ProductInstanceService({ actor: req.user as User }).updateProduct(id, prodId, params); @@ -201,7 +200,7 @@ export class ContractController extends Controller { @Delete('{id}/product/{prodId}') @Security('local', ['GENERAL', 'ADMIN']) @Response(401) - public async deleteProductInstance(id: number, prodId: number, @Request() req: express.Request): Promise { + public async deleteProductInstance(id: number, prodId: number, @Request() req: ExpressRequest): Promise { return new ProductInstanceService({ actor: req.user as User }).deleteProduct(id, prodId); } @@ -219,7 +218,7 @@ export class ContractController extends Controller { id: number, prodId: number, @Body() params: ProductInstanceStatusParams, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateActivityParams(req, [body('subType').isIn(Object.values(ProductInstanceStatus))]); await new ProductInstanceService().validateProductInstanceContractB(id, prodId); @@ -250,7 +249,7 @@ export class ContractController extends Controller { id: number, prodId: number, @Body() params: ActivityParams, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateCommentParams(req); await new ProductInstanceService().validateProductInstanceContractB(id, prodId); @@ -281,7 +280,7 @@ export class ContractController extends Controller { prodId: number, activityId: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateActivityParams(req); await new ProductInstanceService().validateProductInstanceContractB(id, prodId); @@ -323,8 +322,8 @@ export class ContractController extends Controller { public async generateContractFile( id: number, @Body() params: GenerateContractParams, - @Request() req: express.Request, - ): Promise { + @Request() req: ExpressRequest, + ): Promise { await validate( [ body('language').isIn(Object.values(Language)), @@ -354,7 +353,7 @@ export class ContractController extends Controller { @Post('{id}/file/upload') @Security('local', ['GENERAL', 'ADMIN']) @Response(401) - public async uploadContractFile(id: number, @Request() req: express.Request): Promise { + public async uploadContractFile(id: number, @Request() req: ExpressRequest): Promise { const actor = req.user as User; if (req.body.createdAt !== undefined && !actor.hasRole(Roles.ADMIN)) { throw new ApiError( @@ -363,7 +362,7 @@ export class ContractController extends Controller { ); } - return new FileService(ContractFile, { actor: req.user as User }).uploadFile(req, id); + return (await new FileService(ContractFile, { actor: req.user as User }).uploadFile(req, id)) as ContractFile; } /** @@ -375,7 +374,7 @@ export class ContractController extends Controller { @Get('{id}/file/{fileId}') @Security('local', ['SIGNEE', 'FINANCIAL', 'GENERAL', 'ADMIN', 'AUDIT']) @Response(401) - public async getContractFile(id: number, fileId: number): Promise { + public async getContractFile(id: number, fileId: number): Promise { const file = await new FileService(ContractFile).getFile(id, fileId); return FileHelper.putFileInResponse(this, file); @@ -395,7 +394,7 @@ export class ContractController extends Controller { id: number, fileId: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateFileParams(req); return new FileService(ContractFile).updateFile(id, fileId, params); @@ -425,7 +424,7 @@ export class ContractController extends Controller { public async addContractStatus( id: number, @Body() params: ContractStatusParams, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateActivityParams(req, [body('subType').isIn(Object.values(ContractStatus))]); const p: FullActivityParams = { @@ -450,7 +449,7 @@ export class ContractController extends Controller { public async addContractComment( id: number, @Body() params: ActivityParams, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateCommentParams(req); const p: FullActivityParams = { @@ -476,7 +475,7 @@ export class ContractController extends Controller { id: number, activityId: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateActivityParams(req); const p: Partial = { diff --git a/src/controllers/InvoiceController.ts b/src/controllers/InvoiceController.ts index 25708fc..f0aa111 100644 --- a/src/controllers/InvoiceController.ts +++ b/src/controllers/InvoiceController.ts @@ -1,4 +1,4 @@ -import express from 'express'; +import fs from 'fs'; import { body, ValidationChain } from 'express-validator'; import { Invoice } from '../entity/Invoice'; import { ApiError, HTTPStatus, WrappedApiError } from '../helpers/error'; @@ -21,13 +21,14 @@ import { Language } from '../entity/enums/Language'; import { InvoiceStatus } from '../entity/enums/InvoiceStatus'; import { InvoiceSummary } from '../entity/Summaries'; import { Roles } from '../entity/enums/Roles'; +import { ExpressRequest } from '../types'; import { ListParams } from './ListParams'; import { Body, Controller, Post, Route, Put, Tags, Get, Security, Response, Delete, Request } from 'tsoa'; @Route('invoice') @Tags('Invoice') export class InvoiceController extends Controller { - private async validateInvoiceParams(req: express.Request, validations: ValidationChain[] = []) { + private async validateInvoiceParams(req: ExpressRequest, validations: ValidationChain[] = []) { await validate( [ body('title').isString().trim(), @@ -78,9 +79,7 @@ export class InvoiceController extends Controller { @Put('lastseen') @Security('local', ['FINANCIAL']) @Response(401) - // eslint-disable-next-line @typescript-eslint/no-unused-vars public async updateLastSeenByTreasurer(): Promise { - console.log('run run run!'); return new InvoiceService().setTreasurerLastSeen(); } @@ -103,7 +102,7 @@ export class InvoiceController extends Controller { @Post() @Security('local', ['GENERAL', 'ADMIN']) @Response(401) - public async createInvoice(@Request() req: express.Request, @Body() params: InvoiceCreateParams): Promise { + public async createInvoice(@Request() req: ExpressRequest, @Body() params: InvoiceCreateParams): Promise { await this.validateInvoiceParams(req, [body('companyId').isInt(), body('productInstanceIds').isArray()]); return new InvoiceService({ actor: req.user as User }).createInvoice(params); } @@ -120,7 +119,7 @@ export class InvoiceController extends Controller { public async updateInvoice( id: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await this.validateInvoiceParams(req); return new InvoiceService({ actor: req.user as User }).updateInvoice(id, params); @@ -129,7 +128,6 @@ export class InvoiceController extends Controller { /** * Delete an invoice, if it has no products or updated statuses * @param id ID of the invoice - * @param req Express.js request object */ @Delete('{id}') @Security('local', ['GENERAL', 'ADMIN']) @@ -150,7 +148,7 @@ export class InvoiceController extends Controller { public async addProductToInvoice( id: number, @Body() params: { productId: number }, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validate([body('productId').isInt()], req); return new ProductInstanceService().addInvoiceProduct(id, params.productId); @@ -181,8 +179,8 @@ export class InvoiceController extends Controller { public async generateInvoiceFile( id: number, @Body() params: GenerateInvoiceParams, - @Request() req: express.Request, - ): Promise { + @Request() req: ExpressRequest, + ): Promise { await validate( [ body('language').isIn(Object.values(Language)), @@ -209,7 +207,7 @@ export class InvoiceController extends Controller { @Post('{id}/file/upload') @Security('local', ['GENERAL', 'ADMIN']) @Response(401) - public async uploadInvoiceFile(id: number, @Request() req: express.Request): Promise { + public async uploadInvoiceFile(id: number, @Request() req: ExpressRequest): Promise { const actor = req.user as User; if (req.body.createdAt !== undefined && !actor.hasRole(Roles.ADMIN)) { throw new ApiError( @@ -218,7 +216,7 @@ export class InvoiceController extends Controller { ); } - return new FileService(InvoiceFile, { actor: req.user as User }).uploadFile(req, id); + return (await new FileService(InvoiceFile, { actor: req.user as User }).uploadFile(req, id)) as InvoiceFile; } /** @@ -230,7 +228,7 @@ export class InvoiceController extends Controller { @Get('{id}/file/{fileId}') @Security('local', ['SIGNEE', 'FINANCIAL', 'GENERAL', 'ADMIN', 'AUDIT']) @Response(401) - public async getInvoiceFile(id: number, fileId: number): Promise { + public async getInvoiceFile(id: number, fileId: number): Promise { const file = await new FileService(InvoiceFile).getFile(id, fileId); return FileHelper.putFileInResponse(this, file); @@ -250,7 +248,7 @@ export class InvoiceController extends Controller { id: number, fileId: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateFileParams(req); return new FileService(InvoiceFile).updateFile(id, fileId, params); @@ -279,8 +277,8 @@ export class InvoiceController extends Controller { @Response(401) public async generateCustomInvoice( @Body() params: CustomInvoiceGenSettings, - @Request() req: express.Request, - ): Promise { + @Request() req: ExpressRequest, + ): Promise { await validate( [ body('language').isIn(Object.values(Language)), @@ -308,7 +306,7 @@ export class InvoiceController extends Controller { public async addInvoiceStatus( id: number, @Body() params: InvoiceStatusParams, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateActivityParams(req, [body('subType').isIn(Object.values(InvoiceStatus))]); const p: FullActivityParams = { @@ -333,7 +331,7 @@ export class InvoiceController extends Controller { public async addInvoiceComment( id: number, @Body() params: ActivityParams, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateCommentParams(req); const p: FullActivityParams = { @@ -359,7 +357,7 @@ export class InvoiceController extends Controller { id: number, activityId: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateActivityParams(req); const p: Partial = { diff --git a/src/controllers/ListParams.ts b/src/controllers/ListParams.ts index da852b5..19dafa6 100644 --- a/src/controllers/ListParams.ts +++ b/src/controllers/ListParams.ts @@ -18,5 +18,5 @@ export type SortDirection = 'ASC' | 'DESC'; export interface ListOrFilter { column: string; - values: any[]; + values: unknown[]; } diff --git a/src/controllers/ProductCategoryController.ts b/src/controllers/ProductCategoryController.ts index 816945d..24fa0fc 100644 --- a/src/controllers/ProductCategoryController.ts +++ b/src/controllers/ProductCategoryController.ts @@ -1,4 +1,3 @@ -import express from 'express'; import { body } from 'express-validator'; import ProductCategoryService, { CategoryListResponse, @@ -9,13 +8,14 @@ import { WrappedApiError } from '../helpers/error'; import { ProductCategory } from '../entity/ProductCategory'; import { validate } from '../helpers/validation'; import StatisticsService, { ContractedProductsAnalysis } from '../services/StatisticsService'; +import { ExpressRequest } from '../types'; import { ListParams } from './ListParams'; import { Body, Controller, Delete, Get, Post, Put, Request, Response, Route, Security, Tags } from 'tsoa'; @Route('category') @Tags('Product Category') export class ProductCategoryController extends Controller { - private async validateCategoryParams(req: express.Request) { + private async validateCategoryParams(req: ExpressRequest) { await validate([body('name').notEmpty().trim()], req); } @@ -51,7 +51,7 @@ export class ProductCategoryController extends Controller { @Response(401) public async createCategory( @Body() params: CategoryParams, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await this.validateCategoryParams(req); return new ProductCategoryService().createCategory(params); @@ -80,7 +80,7 @@ export class ProductCategoryController extends Controller { public async updateCategory( id: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await this.validateCategoryParams(req); return new ProductCategoryService().updateCategory(id, params); diff --git a/src/controllers/ProductController.ts b/src/controllers/ProductController.ts index 78dbcc4..64689dd 100644 --- a/src/controllers/ProductController.ts +++ b/src/controllers/ProductController.ts @@ -1,4 +1,4 @@ -import express from 'express'; +import fs from 'fs'; import { body } from 'express-validator'; import { Product } from '../entity/Product'; import ProductService, { @@ -24,13 +24,14 @@ import ProductInstanceService, { ProductInstanceListResponse } from '../services import { AnalysisResultByYear } from '../helpers/rawQueries'; import { ProductPricing } from '../entity/ProductPricing'; import { Roles } from '../entity/enums/Roles'; +import { ExpressRequest } from '../types'; import { ListParams, PaginationParams } from './ListParams'; import { Body, Controller, Post, Route, Put, Tags, Get, Request, Response, Security, Delete } from 'tsoa'; @Route('product') @Tags('Product') export class ProductController extends Controller { - private async validateProductParams(req: express.Request) { + private async validateProductParams(req: ExpressRequest) { await validate( [ body('nameDutch').notEmpty().trim(), @@ -93,7 +94,7 @@ export class ProductController extends Controller { @Security('local', ['ADMIN']) @Response(401) @Response(400) - public async createProduct(@Request() req: express.Request, @Body() params: ProductParams): Promise { + public async createProduct(@Request() req: ExpressRequest, @Body() params: ProductParams): Promise { await this.validateProductParams(req); return new ProductService().createProduct(params); } @@ -109,7 +110,7 @@ export class ProductController extends Controller { @Response(401) @Response(400) public async updateProduct( - @Request() req: express.Request, + @Request() req: ExpressRequest, id: number, @Body() params: Partial, ): Promise { @@ -120,7 +121,6 @@ export class ProductController extends Controller { /** * Delete a product, if it has no contracts and/or invoices * @param id ID of the product - * @param req Express.js request object */ @Delete('{id}') @Security('local', ['GENERAL', 'ADMIN']) @@ -137,7 +137,7 @@ export class ProductController extends Controller { @Post('{id}/pricing') @Security('local', ['ADMIN']) @Response(401) - public async addPricing(id: number, @Request() req: express.Request): Promise { + public async addPricing(id: number, @Request() req: ExpressRequest): Promise { return new ProductService({ actor: req.user as User }).addPricing(id); } @@ -153,7 +153,7 @@ export class ProductController extends Controller { public async updatePricing( id: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { return new ProductService({ actor: req.user as User }).updatePricing(id, params); } @@ -166,7 +166,7 @@ export class ProductController extends Controller { @Delete('{id}/pricing') @Security('local', ['ADMIN']) @Response(401) - public async deletePricing(id: number, @Request() req: express.Request): Promise { + public async deletePricing(id: number, @Request() req: ExpressRequest): Promise { return new ProductService({ actor: req.user as User }).deletePricing(id); } @@ -209,7 +209,7 @@ export class ProductController extends Controller { @Post('{id}/file/upload') @Security('local', ['GENERAL', 'ADMIN']) @Response(401) - public async uploadProductFile(id: number, @Request() req: express.Request): Promise { + public async uploadProductFile(id: number, @Request() req: ExpressRequest): Promise { const actor = req.user as User; if (req.body.createdAt !== undefined && !actor.hasRole(Roles.ADMIN)) { throw new ApiError( @@ -218,7 +218,7 @@ export class ProductController extends Controller { ); } - return new FileService(ProductFile, { actor: req.user as User }).uploadFile(req, id); + return (await new FileService(ProductFile, { actor: req.user }).uploadFile(req, id)) as ProductFile; } /** @@ -230,7 +230,7 @@ export class ProductController extends Controller { @Get('{id}/file/{fileId}') @Security('local', ['GENERAL', 'ADMIN']) @Response(401) - public async getProductFile(id: number, fileId: number): Promise { + public async getProductFile(id: number, fileId: number): Promise { const file = await new FileService(ProductFile).getFile(id, fileId); return FileHelper.putFileInResponse(this, file); @@ -250,7 +250,7 @@ export class ProductController extends Controller { id: number, fileId: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateFileParams(req); return new FileService(ProductFile).updateFile(id, fileId, params); @@ -280,7 +280,7 @@ export class ProductController extends Controller { public async addProductComment( id: number, @Body() params: ActivityParams, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateCommentParams(req); const p: FullActivityParams = { @@ -309,7 +309,7 @@ export class ProductController extends Controller { id: number, activityId: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await validateActivityParams(req); const p: Partial = { diff --git a/src/controllers/RootController.ts b/src/controllers/RootController.ts index dbac696..c8a080e 100644 --- a/src/controllers/RootController.ts +++ b/src/controllers/RootController.ts @@ -1,4 +1,3 @@ -import express from 'express'; import { body } from 'express-validator'; import { WrappedApiError } from '../helpers/error'; import { validate } from '../helpers/validation'; @@ -6,6 +5,7 @@ import AuthService, { AuthStatus, Profile } from '../services/AuthService'; import ServerSettingsService, { SetupParams } from '../services/ServerSettingsService'; import StatisticsService from '../services/StatisticsService'; import { ldapEnabled, LoginMethods } from '../auth'; +import { ExpressRequest } from '../types'; import { Body, Controller, Get, Post, Query, Request, Response, Route, Security } from 'tsoa'; export interface ResetPasswordRequest { @@ -26,7 +26,7 @@ export interface GeneralPublicInfo { @Route('') export class RootController extends Controller { @Post('setup') - public async postSetup(@Body() params: SetupParams, @Request() req: express.Request): Promise { + public async postSetup(@Body() params: SetupParams, @Request() req: ExpressRequest): Promise { const user = await new ServerSettingsService().initialSetup(params); if (user === undefined) { return; @@ -35,19 +35,19 @@ export class RootController extends Controller { } @Get('authStatus') - public async getAuthStatus(@Request() req: express.Request): Promise { + public getAuthStatus(@Request() req: ExpressRequest): AuthStatus { return new AuthService().getAuthStatus(req); } @Get('profile') @Security('local') @Response(401) - public async getProfile(@Request() req: express.Request): Promise { + public async getProfile(@Request() req: ExpressRequest): Promise { return new AuthService().getProfile(req); } @Post('logout') - public async logout(@Request() req: express.Request): Promise { + public async logout(@Request() req: ExpressRequest): Promise { return new AuthService().logout(req); } @@ -58,7 +58,7 @@ export class RootController extends Controller { @Post('resetPassword') @Response(400) - public async resetPassword(@Request() req: express.Request, @Body() reqBody: ResetPasswordRequest): Promise { + public async resetPassword(@Request() req: ExpressRequest, @Body() reqBody: ResetPasswordRequest): Promise { await validate([body('password').equals(reqBody.repeatPassword), body('password').isStrongPassword()], req); return new AuthService().resetPassword(reqBody.password, reqBody.token); } @@ -66,21 +66,21 @@ export class RootController extends Controller { @Post('generateApiKey') @Security('local') @Response(400) - public async generateApiKey(@Request() req: express.Request) { + public async generateApiKey(@Request() req: ExpressRequest) { return new AuthService().generateApiKey(req); } @Get('getApiKey') @Security('local') @Response(400) - public async getApiKey(@Request() req: express.Request) { + public async getApiKey(@Request() req: ExpressRequest) { return new AuthService().getApiKey(req); } @Post('revokeApiKey') @Security('local') @Response(400) - public async revokeApiKey(@Request() req: express.Request) { + public async revokeApiKey(@Request() req: ExpressRequest) { await new AuthService().revokeApiKey(req); } diff --git a/src/controllers/UserController.ts b/src/controllers/UserController.ts index ff0490e..77fccc0 100644 --- a/src/controllers/UserController.ts +++ b/src/controllers/UserController.ts @@ -1,4 +1,3 @@ -import express from 'express'; import { body } from 'express-validator'; import { User } from '../entity/User'; import { ApiError, HTTPStatus, WrappedApiError } from '../helpers/error'; @@ -13,11 +12,12 @@ import { IdentityLDAP } from '../entity/IdentityLDAP'; import GDPRService from '../services/GDPRService'; import { ListParams } from './ListParams'; import { Body, Controller, Delete, Get, Post, Put, Request, Response, Route, Security, Tags } from 'tsoa'; +import { ExpressRequest } from 'src/types'; @Route('user') @Tags('User') export class UserController extends Controller { - private async validateUserParams(req: express.Request) { + private async validateUserParams(req: ExpressRequest) { await validate( [ body('email').isEmail().normalizeEmail(), @@ -63,7 +63,7 @@ export class UserController extends Controller { @Get('{id}') @Security('local', ['SIGNEE', 'FINANCIAL', 'GENERAL', 'ADMIN', 'AUDIT']) @Response(401) - public async getUser(id: number, @Request() req: express.Request): Promise { + public async getUser(id: number, @Request() req: ExpressRequest): Promise { const actor = req.user as User; if (actor.id !== id && !actor.hasRole(Roles.ADMIN)) { throw new ApiError( @@ -84,7 +84,7 @@ export class UserController extends Controller { @Security('local', ['ADMIN']) @Response(401) @Response(403) - public async deleteUser(@Request() req: Express.Request, id: number): Promise { + public async deleteUser(@Request() req: ExpressRequest, id: number): Promise { return new UserService().deleteUser(id, req.user as User); } @@ -96,7 +96,7 @@ export class UserController extends Controller { @Post() @Security('local', ['ADMIN']) @Response(401) - public async createUser(@Body() params: UserParams, @Request() req: express.Request): Promise { + public async createUser(@Body() params: UserParams, @Request() req: ExpressRequest): Promise { await this.validateUserParams(req); return new UserService().createUser(params); } @@ -111,7 +111,7 @@ export class UserController extends Controller { @Security('local', ['SIGNEE', 'FINANCIAL', 'GENERAL', 'ADMIN', 'AUDIT']) @Response(401) public async updateUser( - @Request() req: express.Request, + @Request() req: ExpressRequest, id: number, @Body() params: Partial, ): Promise { @@ -135,7 +135,7 @@ export class UserController extends Controller { @Put('{id}/logo') @Security('local', ['SIGNEE', 'FINANCIAL', 'GENERAL', 'ADMIN', 'AUDIT']) @Response(401) - public async uploadUserAvatar(@Request() req: express.Request, id: number) { + public async uploadUserAvatar(@Request() req: ExpressRequest, id: number) { const actor = req.user as User; if (actor.id !== id && !actor.hasRole(Roles.ADMIN)) { throw new ApiError( @@ -157,7 +157,7 @@ export class UserController extends Controller { @Delete('{id}/logo') @Security('local', ['SIGNEE', 'FINANCIAL', 'GENERAL', 'ADMIN', 'AUDIT']) @Response(401) - public async deleteUserAvatar(@Request() req: express.Request, id: number): Promise { + public async deleteUserAvatar(@Request() req: ExpressRequest, id: number): Promise { const actor = req.user as User; if (actor.id !== id && !actor.hasRole(Roles.ADMIN)) { throw new ApiError( @@ -177,7 +177,7 @@ export class UserController extends Controller { @Put('{id}/background') @Security('local', ['SIGNEE', 'FINANCIAL', 'GENERAL', 'ADMIN', 'AUDIT']) @Response(401) - public async uploadUserBackground(@Request() req: express.Request, id: number) { + public async uploadUserBackground(@Request() req: ExpressRequest, id: number) { const actor = req.user as User; if (actor.id !== id) { throw new ApiError( @@ -199,7 +199,7 @@ export class UserController extends Controller { @Delete('{id}/background') @Security('local', ['SIGNEE', 'FINANCIAL', 'GENERAL', 'ADMIN', 'AUDIT']) @Response(401) - public async deleteUserBackground(@Request() req: express.Request, id: number): Promise { + public async deleteUserBackground(@Request() req: ExpressRequest, id: number): Promise { const actor = req.user as User; if (actor.id !== id && !actor.hasRole(Roles.ADMIN)) { throw new ApiError( @@ -221,7 +221,7 @@ export class UserController extends Controller { @Security('local', ['ADMIN', 'GENERAL']) @Response(401) public async transferAssignments( - @Request() req: express.Request, + @Request() req: ExpressRequest, id: number, @Body() params: TransferUserParams, ): Promise { @@ -241,7 +241,7 @@ export class UserController extends Controller { @Post('{id}/auth/local') @Security('local', ['ADMIN']) @Response(401) - public async createLocalIdentity(@Request() req: express.Request, id: number): Promise { + public async createLocalIdentity(@Request() req: ExpressRequest, id: number): Promise { const user = await new UserService().getUser(id); return new AuthService().createIdentityLocal(user, false); } @@ -249,7 +249,7 @@ export class UserController extends Controller { @Delete('{id}/auth/local') @Security('local', ['ADMIN']) @Response(401) - public async deleteLocalIdentity(@Request() req: express.Request, id: number): Promise { + public async deleteLocalIdentity(@Request() req: ExpressRequest, id: number): Promise { const user = await new UserService().getUser(id); return new AuthService().removeIdentityLocal(user); } @@ -258,7 +258,7 @@ export class UserController extends Controller { @Security('local', ['ADMIN']) @Response(401) public async createLdapIdentity( - @Request() req: express.Request, + @Request() req: ExpressRequest, id: number, @Body() params: LdapIdentityParams, ): Promise { @@ -270,7 +270,7 @@ export class UserController extends Controller { @Security('local', ['ADMIN']) @Response(401) public async updateLdapIdentity( - @Request() req: express.Request, + @Request() req: ExpressRequest, id: number, @Body() params: Partial, ): Promise { @@ -281,7 +281,7 @@ export class UserController extends Controller { @Delete('{id}/auth/ldap') @Security('local', ['ADMIN']) @Response(401) - public async deleteLdapIdentity(@Request() req: express.Request, id: number): Promise { + public async deleteLdapIdentity(@Request() req: ExpressRequest, id: number): Promise { const user = await new UserService().getUser(id); return new AuthService().removeIdentityLdap(user); } diff --git a/src/controllers/VATController.ts b/src/controllers/VATController.ts index 75bf33e..e9379a7 100644 --- a/src/controllers/VATController.ts +++ b/src/controllers/VATController.ts @@ -1,16 +1,16 @@ -import express from 'express'; import { body } from 'express-validator'; import VATService, { VATListResponse, VATParams, VATSummary } from '../services/VATService'; import { WrappedApiError } from '../helpers/error'; import { ValueAddedTax } from '../entity/ValueAddedTax'; import { validate } from '../helpers/validation'; +import { ExpressRequest } from '../types'; import { ListParams } from './ListParams'; import { Body, Controller, Get, Post, Put, Request, Response, Route, Security, Tags } from 'tsoa'; @Route('VAT') @Tags('Value Added Tax') export class VATController extends Controller { - private async validateVATParams(req: express.Request) { + private async validateVATParams(req: ExpressRequest) { await validate([body('category').notEmpty().trim()], req); } @@ -59,7 +59,7 @@ export class VATController extends Controller { public async updateVAT( id: number, @Body() params: Partial, - @Request() req: express.Request, + @Request() req: ExpressRequest, ): Promise { await this.validateVATParams(req); return new VATService().updateVAT(id, params); diff --git a/src/helpers/validation.ts b/src/helpers/validation.ts index 1943d3c..531e465 100644 --- a/src/helpers/validation.ts +++ b/src/helpers/validation.ts @@ -1,6 +1,6 @@ -import express from 'express'; import { body, ValidationChain, validationResult } from 'express-validator'; import ContactService from '../services/ContactService'; +import { ExpressRequest } from '../types'; import { ApiError, HTTPStatus } from './error'; /** @@ -8,7 +8,7 @@ import { ApiError, HTTPStatus } from './error'; * @param validations Array of validations to execute on the request * @param req Express.js request object */ -export const validate = async (validations: ValidationChain[], req: express.Request) => { +export const validate = async (validations: ValidationChain[], req: ExpressRequest) => { await Promise.all(validations.map((validation) => validation.run(req))); const errors = validationResult(req); @@ -23,7 +23,7 @@ export const validate = async (validations: ValidationChain[], req: express.Requ * @param validations Array of validations to execute on the request * @param req Express.js request object */ -export const validateSeq = async (validations: ValidationChain[], req: express.Request) => { +export const validateSeq = async (validations: ValidationChain[], req: ExpressRequest) => { for (let i = 0; i < validations.length; i++) { const result = await validations[i].run(req); if (!result.isEmpty()) break; @@ -40,12 +40,12 @@ export const validateSeq = async (validations: ValidationChain[], req: express.R * @param contactId ID of the contact to check * @param req Express.js request object, with the company id in the body */ -export const contactInCompany = (contactId: number, req: express.Request) => { +export const contactInCompany = (contactId: number, req: ExpressRequest) => { new ContactService() .getContact(contactId) .then((contact) => { // TODO how to type body of request? - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (contact.companyId !== req.body.companyId) { return Promise.reject(new Error('Contact does not belong to company')); } @@ -61,7 +61,7 @@ export const contactInCompany = (contactId: number, req: express.Request) => { * @param req Express.js request object * @param validations Optional additional validations to execute */ -export const validateActivityParams = async (req: express.Request, validations: ValidationChain[] = []) => { +export const validateActivityParams = async (req: ExpressRequest, validations: ValidationChain[] = []) => { await validate([body('description').isString().trim()].concat(validations), req); }; @@ -70,7 +70,7 @@ export const validateActivityParams = async (req: express.Request, validations: * @param req Express.js request object * @param validations Optional additional validations to execute */ -export const validateCommentParams = async (req: express.Request, validations: ValidationChain[] = []) => { +export const validateCommentParams = async (req: ExpressRequest, validations: ValidationChain[] = []) => { await validate([body('description').isString().notEmpty().trim()].concat(validations), req); }; @@ -79,6 +79,6 @@ export const validateCommentParams = async (req: express.Request, validations: V * @param req Express.js request object * @param validations Optional additional validations to execute */ -export const validateFileParams = async (req: express.Request, validations: ValidationChain[] = []) => { +export const validateFileParams = async (req: ExpressRequest, validations: ValidationChain[] = []) => { await validate([body('name').trim()].concat(validations), req); }; diff --git a/src/services/AuthService.ts b/src/services/AuthService.ts index 2d02b1e..c284761 100644 --- a/src/services/AuthService.ts +++ b/src/services/AuthService.ts @@ -1,4 +1,3 @@ -import express from 'express'; import { Repository } from 'typeorm'; import jwt, { JwtPayload } from 'jsonwebtoken'; import validator from 'validator'; @@ -14,6 +13,7 @@ import { newApiKey } from '../mailer/templates/newApiKey'; import { viewApiKey } from '../mailer/templates/viewApiKey'; import { IdentityLDAP } from '../entity/IdentityLDAP'; import AppDataSource from '../database'; +import { ExpressRequest } from '../types'; const INVALID_TOKEN = 'Invalid token.'; export interface AuthStatus { @@ -54,7 +54,7 @@ export default class AuthService { this.userRepo = userRepo ?? AppDataSource.getRepository(User); } - getAuthStatus(req: express.Request): AuthStatus { + getAuthStatus(req: ExpressRequest): AuthStatus { const authenticated = req.isAuthenticated(); return { @@ -62,7 +62,7 @@ export default class AuthService { }; } - async getProfile(req: express.Request): Promise { + async getProfile(req: ExpressRequest): Promise { const user = (await this.userRepo.findOne({ where: { id: (req.user as User).id }, relations: ['roles'], @@ -80,7 +80,7 @@ export default class AuthService { } // TODO check error type in case of reject - async logout(req: express.Request): Promise { + async logout(req: ExpressRequest): Promise { return new Promise((resolve, reject) => { req.logout((error: Error) => { if (error) reject(error); @@ -90,7 +90,7 @@ export default class AuthService { } // TODO check error type in case of reject - login(user: User, req: express.Request) { + login(user: User, req: ExpressRequest) { return new Promise((resolve, reject) => { req.logIn(user, (err: Error) => { if (err) { @@ -240,7 +240,7 @@ export default class AuthService { await this.identityLocalRepo.softDelete(id); } - async getApiKey(req: express.Request) { + async getApiKey(req: ExpressRequest) { const user = (await this.userRepo.findOneBy({ id: (req.user as User).id }))!; const identity = await this.identityApiKeyRepo.findOneBy({ id: (req.user as User).id }); @@ -254,7 +254,7 @@ export default class AuthService { return identity.apiKey; } - async generateApiKey(req: express.Request) { + async generateApiKey(req: ExpressRequest) { const user = (await this.userRepo.findOneBy({ id: (req.user as User).id }))!; let identity = await this.identityApiKeyRepo.findOneBy({ id: (req.user as User).id }); @@ -275,7 +275,7 @@ export default class AuthService { return identity.apiKey; } - async revokeApiKey(req: express.Request) { + async revokeApiKey(req: ExpressRequest) { await this.identityApiKeyRepo.delete((req.user as User).id); } } diff --git a/src/services/FileService.ts b/src/services/FileService.ts index 82a12fb..4e1d629 100644 --- a/src/services/FileService.ts +++ b/src/services/FileService.ts @@ -4,7 +4,6 @@ import * as fs from 'fs'; import path from 'path'; import { v4 as uuidv4 } from 'uuid'; import multer from 'multer'; -import express from 'express'; import { Repository } from 'typeorm'; import mime from 'mime'; import BaseFile from '../entity/file/BaseFile'; @@ -36,6 +35,7 @@ import ContactService from './ContactService'; import ContractService from './ContractService'; import InvoiceService from './InvoiceService'; import UserService from './UserService'; +import { ExpressRequest } from '../types'; export interface FileParams { name?: string; @@ -201,7 +201,7 @@ export default class FileService { return file; } - private static handleFile(request: express.Request): Promise { + private static handleFile(request: ExpressRequest): Promise { const multerSingle = multer().single('file'); return new Promise((resolve, reject) => { // @ts-ignore @@ -214,7 +214,7 @@ export default class FileService { }); } - async uploadFile(request: express.Request, entityId: number) { + async uploadFile(request: ExpressRequest, entityId: number) { await FileService.handleFile(request); await validateFileParams(request); const params = { @@ -311,7 +311,7 @@ export default class FileService { Also, they need to process uploading and verifying files, so therefore they are defined in this service. and not in their "own" service. */ - static async uploadCompanyLogo(request: express.Request, companyId: number) { + static async uploadCompanyLogo(request: ExpressRequest, companyId: number) { const company = await new CompanyService().getCompany(companyId); await FileService.handleFile(request); @@ -336,7 +336,7 @@ export default class FileService { } } - static async uploadUserAvatar(request: express.Request, userId: number) { + static async uploadUserAvatar(request: ExpressRequest, userId: number) { const user = await new UserService().getUser(userId); await FileService.handleFile(request); @@ -361,7 +361,7 @@ export default class FileService { } } - static async uploadUserBackground(request: express.Request, userId: number) { + static async uploadUserBackground(request: ExpressRequest, userId: number) { const user = await new UserService().getUser(userId); await FileService.handleFile(request); diff --git a/src/types.d.ts b/src/types.d.ts index 0104aac..1f68f73 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,5 +1,20 @@ +import { Request } from 'express'; import { User as EntityUser } from './entity/User'; +interface CustomBody { + createdAt?: Date; + name?: string; + companyId?: number; + rememberMe?: boolean; +} + +export type ExpressRequest = Request< + Params, + ResBody, + ReqBody, + ReqQuery +>; + declare global { namespace Express { // eslint-disable-next-line @typescript-eslint/no-empty-object-type From 08d060519d701891eb468cdb72fa2a6a3c472426 Mon Sep 17 00:00:00 2001 From: Gijsdeman Date: Wed, 26 Feb 2025 22:23:08 +0100 Subject: [PATCH 9/9] refactor: last lint issues --- package.json | 2 +- src/auth/LDAPStrategy.ts | 26 ++++++++++++++++++++------ src/auth/LocalStrategy.ts | 6 ++++-- src/controllers/CompanyController.ts | 4 ++-- src/controllers/ContractController.ts | 6 +++--- src/controllers/InvoiceController.ts | 8 ++++---- src/controllers/ListParams.ts | 3 ++- src/controllers/ProductController.ts | 4 ++-- src/helpers/fileHelper.ts | 3 ++- src/timedevents/events/ldapGroups.ts | 5 +++-- tsconfig.json | 3 +-- yarn.lock | 24 ++++++++++++------------ 12 files changed, 56 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index 565dd70..de84f10 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "gen-client": "nswag openapi2tsclient /input:src/public/swagger.json /output:../parelpracht-client/src/clients/server.generated.ts /ServiceHost:.", "db:diagram": "typeorm-uml ormconfig.json", "db:validate": "ts-node src/dbvalidator/validate.ts", - "lint": "eslint src", + "lint": "yarn tsoa && eslint src", "lint:fix": "eslint . --fix", "format": "prettier --ignore-path .gitignore --check .", "format:fix": "prettier --ignore-path .gitignore --write ." diff --git a/src/auth/LDAPStrategy.ts b/src/auth/LDAPStrategy.ts index 491ff71..599eee5 100644 --- a/src/auth/LDAPStrategy.ts +++ b/src/auth/LDAPStrategy.ts @@ -12,6 +12,19 @@ import { ExpressRequest } from '../types'; const isDefined = (i: string | undefined) => i !== undefined && i !== ''; +export interface LDAPUser { + sAMAccountName: string; + memberOfFlattened: string[]; + memberOf: string[]; + mail: string; + givenName: string; + sn: string; +} + +interface AuthInfo { + message: string; +} + export const ldapEnabled = () => isDefined(process.env.LDAP_URL) && isDefined(process.env.LDAP_BINDDN) && @@ -29,7 +42,7 @@ export const LDAPStrategy = new Strategy({ }, }); -const checkAllowedRoles = async (ldapUser: any): Promise => { +const checkAllowedRoles = async (ldapUser: LDAPUser): Promise => { const roles = await AppDataSource.getRepository(Role).find(); const userRoles: Roles[] = []; roles.forEach((role) => { @@ -40,7 +53,7 @@ const checkAllowedRoles = async (ldapUser: any): Promise => { return userRoles; }; -export const updateUserInformation = async (user: User, ldapUser: any): Promise => { +export const updateUserInformation = async (user: User, ldapUser: LDAPUser): Promise => { const userRoles = await checkAllowedRoles(ldapUser); await new UserService().assignRoles(user, userRoles); @@ -55,7 +68,8 @@ export const updateUserInformation = async (user: User, ldapUser: any): Promise< }; export const ldapLogin = (req: ExpressRequest, res: express.Response, next: express.NextFunction) => { - passport.authenticate('ldapauth', async (err: any, ldapUser: any, info: any) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call -- this seems to be correct + passport.authenticate('ldapauth', async (err: Error, ldapUser: LDAPUser, info: AuthInfo) => { if (err) { return next(err); } @@ -85,13 +99,13 @@ export const ldapLogin = (req: ExpressRequest, res: express.Response, next: expr lastName: ldapUser.sn, email: ldapUser.mail, function: '', - } as any as User; + } as User; user = await userRepo.save(user); identity = { id: user.id, username: ldapUser.sAMAccountName, - } as any as IdentityLDAP; + } as IdentityLDAP; identity = await identityRepo.save(identity); identity = await identityRepo.findOne({ where: { id: identity.id }, @@ -105,7 +119,7 @@ export const ldapLogin = (req: ExpressRequest, res: express.Response, next: expr await updateUserInformation(identity.user, ldapUser); - return req.logIn(identity.user, (e: any) => { + return req.logIn(identity.user, (e: Error) => { // When the user enabled "remember me", we give the session cookie an // expiration date of 30 days if (req.body.rememberMe === true) { diff --git a/src/auth/LocalStrategy.ts b/src/auth/LocalStrategy.ts index 55c0556..5617c96 100644 --- a/src/auth/LocalStrategy.ts +++ b/src/auth/LocalStrategy.ts @@ -33,6 +33,7 @@ export default new LocalStrategy( usernameField: 'email', passwordField: 'password', }, + // eslint-disable-next-line @typescript-eslint/no-misused-promises -- async is allowed here async (email, password, done) => { const userRepo = AppDataSource.getRepository(User); const identityRepo = AppDataSource.getRepository(IdentityLocal); @@ -69,14 +70,15 @@ export default new LocalStrategy( ); export const localLogin = (req: ExpressRequest, res: express.Response, next: express.NextFunction) => { - passport.authenticate('local', (err: any, user: any) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call -- this seems to be correct + passport.authenticate('local', (err: Error, user: User) => { if (err) { return next(err); } if (!user) { return next(new ApiError(HTTPStatus.BadRequest, INVALID_LOGIN)); } - return req.logIn(user, (e: any) => { + return req.logIn(user, (e: Error) => { // When the user enabled "remember me", we give the session cookie an // expiration date of 30 days if (req.body.rememberMe === true) { diff --git a/src/controllers/CompanyController.ts b/src/controllers/CompanyController.ts index af31868..28cfe46 100644 --- a/src/controllers/CompanyController.ts +++ b/src/controllers/CompanyController.ts @@ -1,4 +1,4 @@ -import fs from 'fs'; +import { Readable } from 'stream'; import { body } from 'express-validator'; import { Company } from '../entity/Company'; import { Invoice } from '../entity/Invoice'; @@ -219,7 +219,7 @@ export class CompanyController extends Controller { @Get('{id}/file/{fileId}') @Security('local', ['GENERAL', 'ADMIN']) @Response(401) - public async getCompanyFile(id: number, fileId: number): Promise { + public async getCompanyFile(id: number, fileId: number): Promise { const file = await new FileService(CompanyFile).getFile(id, fileId); return FileHelper.putFileInResponse(this, file); diff --git a/src/controllers/ContractController.ts b/src/controllers/ContractController.ts index 9fb8450..1e89a4a 100644 --- a/src/controllers/ContractController.ts +++ b/src/controllers/ContractController.ts @@ -1,4 +1,4 @@ -import fs from 'fs'; +import { Readable } from 'stream'; import { body } from 'express-validator'; import { Contract } from '../entity/Contract'; import ContractService, { ContractListResponse, ContractParams } from '../services/ContractService'; @@ -323,7 +323,7 @@ export class ContractController extends Controller { id: number, @Body() params: GenerateContractParams, @Request() req: ExpressRequest, - ): Promise { + ): Promise { await validate( [ body('language').isIn(Object.values(Language)), @@ -374,7 +374,7 @@ export class ContractController extends Controller { @Get('{id}/file/{fileId}') @Security('local', ['SIGNEE', 'FINANCIAL', 'GENERAL', 'ADMIN', 'AUDIT']) @Response(401) - public async getContractFile(id: number, fileId: number): Promise { + public async getContractFile(id: number, fileId: number): Promise { const file = await new FileService(ContractFile).getFile(id, fileId); return FileHelper.putFileInResponse(this, file); diff --git a/src/controllers/InvoiceController.ts b/src/controllers/InvoiceController.ts index f0aa111..581b065 100644 --- a/src/controllers/InvoiceController.ts +++ b/src/controllers/InvoiceController.ts @@ -1,4 +1,4 @@ -import fs from 'fs'; +import { Readable } from 'stream'; import { body, ValidationChain } from 'express-validator'; import { Invoice } from '../entity/Invoice'; import { ApiError, HTTPStatus, WrappedApiError } from '../helpers/error'; @@ -180,7 +180,7 @@ export class InvoiceController extends Controller { id: number, @Body() params: GenerateInvoiceParams, @Request() req: ExpressRequest, - ): Promise { + ): Promise { await validate( [ body('language').isIn(Object.values(Language)), @@ -228,7 +228,7 @@ export class InvoiceController extends Controller { @Get('{id}/file/{fileId}') @Security('local', ['SIGNEE', 'FINANCIAL', 'GENERAL', 'ADMIN', 'AUDIT']) @Response(401) - public async getInvoiceFile(id: number, fileId: number): Promise { + public async getInvoiceFile(id: number, fileId: number): Promise { const file = await new FileService(InvoiceFile).getFile(id, fileId); return FileHelper.putFileInResponse(this, file); @@ -278,7 +278,7 @@ export class InvoiceController extends Controller { public async generateCustomInvoice( @Body() params: CustomInvoiceGenSettings, @Request() req: ExpressRequest, - ): Promise { + ): Promise { await validate( [ body('language').isIn(Object.values(Language)), diff --git a/src/controllers/ListParams.ts b/src/controllers/ListParams.ts index 19dafa6..e7b8b24 100644 --- a/src/controllers/ListParams.ts +++ b/src/controllers/ListParams.ts @@ -18,5 +18,6 @@ export type SortDirection = 'ASC' | 'DESC'; export interface ListOrFilter { column: string; - values: unknown[]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO check if change required after rewriting queries + values: any[]; } diff --git a/src/controllers/ProductController.ts b/src/controllers/ProductController.ts index 64689dd..d3060b5 100644 --- a/src/controllers/ProductController.ts +++ b/src/controllers/ProductController.ts @@ -1,4 +1,4 @@ -import fs from 'fs'; +import { Readable } from 'stream'; import { body } from 'express-validator'; import { Product } from '../entity/Product'; import ProductService, { @@ -230,7 +230,7 @@ export class ProductController extends Controller { @Get('{id}/file/{fileId}') @Security('local', ['GENERAL', 'ADMIN']) @Response(401) - public async getProductFile(id: number, fileId: number): Promise { + public async getProductFile(id: number, fileId: number): Promise { const file = await new FileService(ProductFile).getFile(id, fileId); return FileHelper.putFileInResponse(this, file); diff --git a/src/helpers/fileHelper.ts b/src/helpers/fileHelper.ts index c2650b7..7400c11 100644 --- a/src/helpers/fileHelper.ts +++ b/src/helpers/fileHelper.ts @@ -1,5 +1,6 @@ import * as fs from 'fs'; import path from 'path'; +import { Readable } from 'stream'; import mime from 'mime'; import BaseFile from '../entity/file/BaseFile'; import { Controller } from 'tsoa'; @@ -18,7 +19,7 @@ export default class FileHelper { * @param controller Controller that handles the request * @param file File to add to the response */ - public static putFileInResponse(controller: Controller, file: BaseFile): fs.ReadStream { + public static putFileInResponse(controller: Controller, file: BaseFile): Readable { const stat = fs.statSync(file.location); controller.setStatus(200); diff --git a/src/timedevents/events/ldapGroups.ts b/src/timedevents/events/ldapGroups.ts index 57e64d9..dc73fb3 100644 --- a/src/timedevents/events/ldapGroups.ts +++ b/src/timedevents/events/ldapGroups.ts @@ -1,6 +1,6 @@ import { createClient, SearchCallbackResponse, SearchEntry } from 'ldapjs'; import { IdentityLDAP } from '../../entity/IdentityLDAP'; -import { updateUserInformation } from '../../auth'; +import { LDAPUser, updateUserInformation } from '../../auth'; import AppDataSource from '../../database'; export default async function ldapGroups() { @@ -28,7 +28,8 @@ export default async function ldapGroups() { } res.on('searchEntry', (entry: SearchEntry) => { - updateUserInformation(identity.user, entry.object).catch((err) => console.error(err)); + // TODO check if there is a better way to cast this type + updateUserInformation(identity.user, entry.object as unknown as LDAPUser).catch((err) => console.error(err)); }); }, ); diff --git a/tsconfig.json b/tsconfig.json index d7d9e12..18c92c9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -39,11 +39,10 @@ /* Advanced Options */ "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true }, "ts-node": { "files": true }, - "include": ["src", "src/**/*.json", "build", "build/**/*.json"], + "include": ["src", "src/**/*.json", "build/**/*.ts", "build/**/*.json"], "exclude": ["node_modules", "dist"] } diff --git a/yarn.lock b/yarn.lock index c94c276..99811b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1608,13 +1608,13 @@ __metadata: linkType: hard "axios@npm:*, axios@npm:^1.7.9": - version: 1.7.9 - resolution: "axios@npm:1.7.9" + version: 1.8.1 + resolution: "axios@npm:1.8.1" dependencies: follow-redirects: "npm:^1.15.6" form-data: "npm:^4.0.0" proxy-from-env: "npm:^1.1.0" - checksum: 10c0/b7a41e24b59fee5f0f26c1fc844b45b17442832eb3a0fb42dd4f1430eb4abc571fe168e67913e8a1d91c993232bd1d1ab03e20e4d1fee8c6147649b576fc1b0b + checksum: 10c0/b2e1d5a61264502deee4b50f0a6df0aa3b174c546ccf68c0dff714a2b8863232e0bd8cb5b84f853303e97f242a98260f9bb9beabeafe451ad5af538e9eb7ac22 languageName: node linkType: hard @@ -2465,13 +2465,13 @@ __metadata: linkType: hard "eslint-config-prettier@npm:^10.0.1": - version: 10.0.1 - resolution: "eslint-config-prettier@npm:10.0.1" + version: 10.0.2 + resolution: "eslint-config-prettier@npm:10.0.2" peerDependencies: eslint: ">=7.0.0" bin: eslint-config-prettier: build/bin/cli.js - checksum: 10c0/e2434931669d211663c0493f2c1640a670a02ba4503a68f056a7eda133f383acbbb983a4a7bd0ad6cb3b2bc4d5731c3be8b32fe28e35087a76fea45f7061ae70 + checksum: 10c0/e0ef3c442661a26fc6e82acec5bb9a418c4a8f65ec8adf0983d3aaba7716d2ed448358b063cce6e3c272c847d14cb856ddf30031770c6571e2b2c3e2a439afd4 languageName: node linkType: hard @@ -2839,11 +2839,11 @@ __metadata: linkType: hard "fastq@npm:^1.6.0": - version: 1.19.0 - resolution: "fastq@npm:1.19.0" + version: 1.19.1 + resolution: "fastq@npm:1.19.1" dependencies: reusify: "npm:^1.0.4" - checksum: 10c0/d6a001638f1574a696660fcbba5300d017760432372c801632c325ca7c16819604841c92fd3ccadcdacec0966ca336363a5ff57bc5f0be335d8ea7ac6087b98f + checksum: 10c0/ebc6e50ac7048daaeb8e64522a1ea7a26e92b3cee5cd1c7f2316cdca81ba543aa40a136b53891446ea5c3a67ec215fbaca87ad405f102dd97012f62916905630 languageName: node linkType: hard @@ -5449,9 +5449,9 @@ __metadata: linkType: hard "reusify@npm:^1.0.4": - version: 1.0.4 - resolution: "reusify@npm:1.0.4" - checksum: 10c0/c19ef26e4e188f408922c46f7ff480d38e8dfc55d448310dfb518736b23ed2c4f547fb64a6ed5bdba92cd7e7ddc889d36ff78f794816d5e71498d645ef476107 + version: 1.1.0 + resolution: "reusify@npm:1.1.0" + checksum: 10c0/4eff0d4a5f9383566c7d7ec437b671cc51b25963bd61bf127c3f3d3f68e44a026d99b8d2f1ad344afff8d278a8fe70a8ea092650a716d22287e8bef7126bb2fa languageName: node linkType: hard