diff options
author | bobzel <zzzman@gmail.com> | 2025-07-21 12:45:55 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2025-07-21 12:45:55 -0400 |
commit | 401431d732fecd6bdef69d83e21253e1b157416d (patch) | |
tree | 77348c17ec94779033982c8f362c775b0564aa34 | |
parent | 3b0fca96e8350c4d103833a0cee6dcdc5e781d5c (diff) |
cleaning up server warnings/errors
-rw-r--r-- | src/client/views/GestureOverlay.tsx | 2 | ||||
-rw-r--r-- | src/client/views/PropertiesView.tsx | 1 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 1 | ||||
-rw-r--r-- | src/client/views/nodes/ImageBox.tsx | 1 | ||||
-rw-r--r-- | src/client/views/smartdraw/SmartDrawHandler.tsx | 2 | ||||
-rw-r--r-- | src/server/ApiManagers/AssistantManager.ts | 4 | ||||
-rw-r--r-- | src/server/ApiManagers/AzureManager.ts | 43 | ||||
-rw-r--r-- | src/server/ApiManagers/UserManager.ts | 29 | ||||
-rw-r--r-- | src/server/RouteManager.ts | 46 | ||||
-rw-r--r-- | src/server/authentication/AuthenticationManager.ts | 44 | ||||
-rw-r--r-- | src/server/authentication/DashUserModel.ts | 87 | ||||
-rw-r--r-- | src/server/authentication/Passport.ts | 13 |
12 files changed, 139 insertions, 134 deletions
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 8488c5293..113250a99 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -50,9 +50,7 @@ interface GestureOverlayProps { * drew or perform the gesture's action */ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChildren<GestureOverlayProps>> { - // eslint-disable-next-line no-use-before-define static Instance: GestureOverlay; - // eslint-disable-next-line no-use-before-define static Instances: GestureOverlay[] = []; @observable public SavedColor?: string = undefined; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 5211272b0..f7c4b464c 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -58,7 +58,6 @@ interface PropertiesViewProps { export class PropertiesView extends ObservableReactComponent<PropertiesViewProps> { private _widthUndo?: UndoManager.Batch; - // eslint-disable-next-line no-use-before-define public static Instance: PropertiesView; constructor(props: PropertiesViewProps) { super(props); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 49c684ab1..73856f47b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -105,7 +105,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection /** * The Freeformview below the cursor at the start of a gesture (that receives the pointerDown event). Used by GestureOverlay to determine the doc a gesture should apply to. */ - // eslint-disable-next-line no-use-before-define public static DownFfview: CollectionFreeFormView | undefined; // the first DocView that receives a pointerdown event. used by GestureOverlay to determine the doc a gesture should apply to. private _clusters = new CollectionFreeFormClusters(this); diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 4886f0e96..617a09ed5 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -49,7 +49,6 @@ import { gptImageLabel } from '../../apis/gpt/GPT'; const DefaultPath = '/assets/unknown-file-icon-hi.png'; export class ImageEditorData { - // eslint-disable-next-line no-use-before-define private static _instance: ImageEditorData; private static get imageData() { return (ImageEditorData._instance ?? new ImageEditorData()).imageData; } // prettier-ignore @observable imageData: { rootDoc: Doc | undefined; open: boolean; source: string; addDoc: Opt<(doc: Doc | Doc[], annotationKey?: string) => boolean> } = observable({ rootDoc: undefined, open: false, source: '', addDoc: undefined }); diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx index b7ff5fff7..a017dd7eb 100644 --- a/src/client/views/smartdraw/SmartDrawHandler.tsx +++ b/src/client/views/smartdraw/SmartDrawHandler.tsx @@ -450,7 +450,7 @@ export class SmartDrawHandler extends ObservableReactComponent<object> { }, }} checked={this._generateDrawing} - onChange={() => this._canInteract && (this._generateDrawing = !this._generateDrawing)} + onChange={action(() => this._canInteract && (this._generateDrawing = !this._generateDrawing))} /> </div> <div className="image-checkbox"> diff --git a/src/server/ApiManagers/AssistantManager.ts b/src/server/ApiManagers/AssistantManager.ts index af25722a4..20ec0dfe6 100644 --- a/src/server/ApiManagers/AssistantManager.ts +++ b/src/server/ApiManagers/AssistantManager.ts @@ -439,9 +439,9 @@ export default class AssistantManager extends ApiManager { try { const image = await openai.images.generate({ model: 'dall-e-3', prompt: image_prompt, response_format: 'url' }); console.log(image); - const result = await DashUploadUtils.UploadImage(image.data[0].url!); + const url = image.data?.[0].url; - const url = image.data[0].url; + const result = url ? await DashUploadUtils.UploadImage(url) : { error: 'Image generation failed' }; res.send({ result, url }); } catch (error) { diff --git a/src/server/ApiManagers/AzureManager.ts b/src/server/ApiManagers/AzureManager.ts index 2d0ab3aa6..d54b15810 100644 --- a/src/server/ApiManagers/AzureManager.ts +++ b/src/server/ApiManagers/AzureManager.ts @@ -1,37 +1,38 @@ -import { ContainerClient, BlobServiceClient } from "@azure/storage-blob"; -import * as fs from "fs"; -import { Readable, Stream } from "stream"; -import * as path from "path"; +import { ContainerClient, BlobServiceClient } from '@azure/storage-blob'; +import * as fs from 'fs'; +import { Readable } from 'stream'; +import * as path from 'path'; const AZURE_STORAGE_CONNECTION_STRING = process.env.AZURE_STORAGE_CONNECTION_STRING; const extToType: { [suffix: string]: string } = { - ".jpeg" : "image/jpeg", - ".jpg" : "image/jpeg", - ".png" : "image/png", - ".svg" : "image/svg+xml", - ".webp" : "image/webp", - ".gif" : "image/gif" -} + '.jpeg': 'image/jpeg', + '.jpg': 'image/jpeg', + '.png': 'image/png', + '.svg': 'image/svg+xml', + '.webp': 'image/webp', + '.gif': 'image/gif', +}; export class AzureManager { private _containerClient: ContainerClient; private _blobServiceClient: BlobServiceClient; private static _instance: AzureManager | undefined; - public static CONTAINER_NAME = "dashmedia"; - public static STORAGE_ACCOUNT_NAME = "dashblobstore"; + public static CONTAINER_NAME = 'dashmedia'; + public static STORAGE_ACCOUNT_NAME = 'dashblobstore'; public static BASE_STRING = `https://${AzureManager.STORAGE_ACCOUNT_NAME}.blob.core.windows.net/${AzureManager.CONTAINER_NAME}`; constructor() { if (!AZURE_STORAGE_CONNECTION_STRING) { - throw new Error("Azure Storage Connection String Not Found"); + throw new Error('Azure Storage Connection String Not Found'); } this._blobServiceClient = BlobServiceClient.fromConnectionString(AZURE_STORAGE_CONNECTION_STRING); this._containerClient = this.BlobServiceClient.getContainerClient(AzureManager.CONTAINER_NAME); } public static get Instance() { - return this._instance = this._instance ?? new AzureManager(); + this._instance = this._instance ?? new AzureManager(); + return this._instance; } public get BlobServiceClient() { @@ -44,14 +45,14 @@ export class AzureManager { public static UploadBlob(filename: string, filepath: string, filetype: string) { const blockBlobClient = this.Instance.ContainerClient.getBlockBlobClient(filename); - const blobOptions = { blobHTTPHeaders: { blobContentType: filetype }}; + const blobOptions = { blobHTTPHeaders: { blobContentType: filetype } }; const stream = fs.createReadStream(filepath); return blockBlobClient.uploadStream(stream, undefined, undefined, blobOptions); } public static UploadBase64ImageBlob(filename: string, data: string, filetype?: string) { const confirmedFiletype = filetype ? filetype : extToType[path.extname(filename)]; - const buffer = Buffer.from(data, "base64"); + const buffer = Buffer.from(data, 'base64'); const blockBlobClient = this.Instance.ContainerClient.getBlockBlobClient(filename); const blobOptions = { blobHTTPHeaders: { blobContentType: confirmedFiletype } }; return blockBlobClient.upload(buffer, buffer.length, blobOptions); @@ -59,7 +60,7 @@ export class AzureManager { public static UploadBlobStream(stream: Readable, filename: string, filetype: string) { const blockBlobClient = this.Instance.ContainerClient.getBlockBlobClient(filename); - const blobOptions = { blobHTTPHeaders: { blobContentType: filetype }}; + const blobOptions = { blobHTTPHeaders: { blobContentType: filetype } }; return blockBlobClient.uploadStream(stream, undefined, undefined, blobOptions); } @@ -74,9 +75,9 @@ export class AzureManager { console.log(`${blob.name}`); const blobItem = { - url : `https://${AzureManager.STORAGE_ACCOUNT_NAME}.blob.core.windows.net/${AzureManager.CONTAINER_NAME}/${blob.name}`, - name : blob.name - } + url: `https://${AzureManager.STORAGE_ACCOUNT_NAME}.blob.core.windows.net/${AzureManager.CONTAINER_NAME}/${blob.name}`, + name: blob.name, + }; foundBlobs.push(blobItem); } diff --git a/src/server/ApiManagers/UserManager.ts b/src/server/ApiManagers/UserManager.ts index b587340e2..b42c974ac 100644 --- a/src/server/ApiManagers/UserManager.ts +++ b/src/server/ApiManagers/UserManager.ts @@ -22,6 +22,7 @@ export default class UserManager extends ApiManager { secureHandler: async ({ res }) => { const cursor = await Database.Instance.query({}, { email: 1, linkDatabaseId: 1, sharingDocumentId: 1 }, 'users'); const results = await cursor.toArray(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any res.send(results.map((user: any) => ({ email: user.email, linkDatabaseId: user.linkDatabaseId, sharingDocumentId: user.sharingDocumentId }))); }, }); @@ -31,9 +32,10 @@ export default class UserManager extends ApiManager { subscription: '/setCacheDocumentIds', secureHandler: async ({ user, req, res }) => { const userModel = user; - const result: any = {}; + const result: { error?: unknown } = {}; userModel.cacheDocumentIds = req.body.cacheDocumentIds; - userModel.save().then(undefined, (err: any) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + userModel.save?.().then(undefined, (err: any) => { if (err) { result.error = [{ msg: 'Error while caching documents' }]; } @@ -90,20 +92,19 @@ export default class UserManager extends ApiManager { subscription: '/internalResetPassword', secureHandler: async ({ user, req, res }) => { const userModel = user; - const result: any = {}; - // eslint-disable-next-line camelcase + const result: { error?: unknown } = {}; const { curr_pass, new_pass } = req.body; // perhaps should assert whether curr password is entered correctly const validated = await new Promise<Opt<boolean>>(resolve => { - bcrypt.compare(curr_pass, userModel.password, (err, passwordsMatch) => { - if (err || !passwordsMatch) { - result.error = [{ msg: 'Incorrect current password' }]; - res.send(result); - resolve(undefined); - } else { - resolve(passwordsMatch); - } - }); + userModel.password && + bcrypt.compare(curr_pass, userModel.password, (err, passwordsMatch) => { + if (err || !passwordsMatch) { + res.send({ error: [{ msg: 'Incorrect current password' }] }); + resolve(undefined); + } else { + resolve(passwordsMatch); + } + }); }); if (validated === undefined) { @@ -133,7 +134,7 @@ export default class UserManager extends ApiManager { userModel.passwordResetExpires = undefined; } - userModel.save().then(undefined, err => { + userModel.save?.().then(undefined, err => { if (err) { result.error = [{ msg: 'Error while saving new password' }]; } diff --git a/src/server/RouteManager.ts b/src/server/RouteManager.ts index c5d70da3d..ed51aea40 100644 --- a/src/server/RouteManager.ts +++ b/src/server/RouteManager.ts @@ -18,10 +18,11 @@ export interface CoreArguments { isRelease: boolean; } -export type AuthorizedCore = CoreArguments & { user: DashUserModel }; -export type SecureHandler = (core: AuthorizedCore) => any | Promise<any>; -export type PublicHandler = (core: CoreArguments) => any | Promise<any>; -export type ErrorHandler = (core: CoreArguments & { error: any }) => any | Promise<any>; +export type AuthorizedCore = CoreArguments & { user: Partial<DashUserModel> }; +export type SecureHandler = (core: AuthorizedCore) => unknown | Promise<unknown>; +export type PublicHandler = (core: CoreArguments) => unknown | Promise<unknown>; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type ErrorHandler = (core: CoreArguments & { error: any }) => unknown | Promise<unknown>; export const STATUS = { OK: 200, @@ -30,13 +31,14 @@ export const STATUS = { PERMISSION_DENIED: 403, }; +// eslint-disable-next-line @typescript-eslint/no-explicit-any export function _error(res: Response, message: string, error?: any) { console.error(message, error); res.statusMessage = message; res.status(STATUS.EXECUTION_ERROR).send(error); } -export function _success(res: Response, body: any) { +export function _success(res: Response, body: unknown) { res.status(STATUS.OK).send(body); } @@ -135,18 +137,6 @@ export default class RouteManager { user = { id: 'guest', email: 'guest', userDocumentId: Utils.GuestID() }; } const core = { req, res, isRelease }; - const tryExecute = async (toExecute: (args: any) => any | Promise<any>, args: any) => { - try { - await toExecute(args); - } catch (e) { - console.log(red(target), user && 'email' in user ? '<user logged out>' : undefined); - if (errorHandler) { - errorHandler({ ...core, error: e }); - } else { - _error(res, `The server encountered an internal error when serving ${target}.`, e); - } - } - }; if (user) { if (requireAdmin && isRelease && process.env.PASSWORD) { if (AdminPrivileges.get(user.id)) { @@ -156,11 +146,29 @@ export default class RouteManager { return; } } - await tryExecute(secureHandler, { ...core, user }); + try { + await secureHandler({ ...core, user }); + } catch (e) { + console.log(red(target), user && 'email' in user ? '<user logged out>' : undefined); + if (errorHandler) { + errorHandler({ ...core, error: e }); + } else { + _error(res, `The server encountered an internal error when serving ${target}.`, e); + } + } } // req.session!.target = target; else if (publicHandler) { - await tryExecute(publicHandler, core); + try { + await publicHandler(core); + } catch (e) { + console.log(red(target), user && 'email' in user ? '<user logged out>' : undefined); + if (errorHandler) { + errorHandler({ ...core, error: e }); + } else { + _error(res, `The server encountered an internal error when serving ${target}.`, e); + } + } if (!res.headersSent) { // res.redirect("/login"); } diff --git a/src/server/authentication/AuthenticationManager.ts b/src/server/authentication/AuthenticationManager.ts index 0cc1553c0..3c7858a72 100644 --- a/src/server/authentication/AuthenticationManager.ts +++ b/src/server/authentication/AuthenticationManager.ts @@ -26,21 +26,12 @@ export const getSignup = (req: Request, res: Response) => { return undefined; }; -const tryRedirectToTarget = (req: Request, res: Response) => { - const target = (req.session as any)?.target; - if (req.session && target) { - res.redirect(target); - } else { - res.redirect('/home'); - } -}; - /** * POST /signup * Create a new local account. */ export const postSignup = (req: Request, res: Response, next: NextFunction) => { - const email = req.body.email as String; + const email = req.body.email as string; check('email', 'Email is not valid').isEmail().run(req); check('password', 'Password must be at least 4 characters long').isLength({ min: 4 }).run(req); check('confirmPassword', 'Passwords do not match').equals(req.body.password).run(req); @@ -66,7 +57,7 @@ export const postSignup = (req: Request, res: Response, next: NextFunction) => { const user = new User(model); User.findOne({ email }) - .then((existingUser: any) => { + .then((existingUser: DashUserModel | null) => { if (existingUser) { return res.redirect('/login'); } @@ -74,13 +65,15 @@ export const postSignup = (req: Request, res: Response, next: NextFunction) => { .then(() => { req.logIn(user, err => { if (err) return next(err); - tryRedirectToTarget(req, res); + res.redirect('/home'); return undefined; }); }) + // eslint-disable-next-line @typescript-eslint/no-explicit-any .catch((err: any) => next(err)); return undefined; }) + // eslint-disable-next-line @typescript-eslint/no-explicit-any .catch((err: any) => next(err)); return undefined; }; @@ -108,7 +101,8 @@ export const getLogin = (req: Request, res: Response) => { export const postLogin = (req: Request, res: Response, next: NextFunction) => { if (req.body.email === '') { User.findOne({ email: 'guest' }) - .then((user: any) => !user && initializeGuest()) + .then((user: DashUserModel | null) => !user && initializeGuest()) + // eslint-disable-next-line @typescript-eslint/no-explicit-any .catch((err: any) => err); req.body.email = 'guest'; req.body.password = 'guest'; @@ -132,7 +126,7 @@ export const postLogin = (req: Request, res: Response, next: NextFunction) => { req.logIn(user, loginErr => { if (loginErr) { next(loginErr); - } else tryRedirectToTarget(req, res); + } else res.redirect('/home'); }); return undefined; }; @@ -163,15 +157,15 @@ export const postForgot = function (req: Request, res: Response, next: NextFunct const { email } = req.body; async.waterfall( [ - function (done: any) { - c.randomBytes(20, (err: any, buffer: Buffer) => { + function (done: (arg: null, token?: string) => void) { + c.randomBytes(20, (err: Error | null, buffer: Buffer) => { if (err) { done(null); } else done(null, buffer.toString('hex')); }); }, - function (token: string, done: any) { - User.findOne({ email }).then((user: any) => { + function (token: string, done: (arg: null, token: string, user: DashUserModel) => void) { + User.findOne({ email }).then((user: DashUserModel | null) => { if (!user) { // NO ACCOUNT WITH SUBMITTED EMAIL res.redirect('/forgotPassword'); @@ -182,7 +176,7 @@ export const postForgot = function (req: Request, res: Response, next: NextFunct user.save().then(() => done(null, token, user)); }); }, - function (token: Uint16Array, user: DashUserModel, done: any) { + function (token: Uint16Array, user: DashUserModel, done: (arg: null, token: Error | null, data: string) => void) { const smtpTransport = nodemailer.createTransport({ service: 'Gmail', auth: { @@ -220,7 +214,7 @@ export const postForgot = function (req: Request, res: Response, next: NextFunct export const getReset = function (req: Request, res: Response) { User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }) - .then((user: any) => { + .then((user: DashUserModel | null) => { if (!user) return res.redirect('/forgotPassword'); res.render('reset.pug', { title: 'Reset Password', @@ -234,9 +228,9 @@ export const getReset = function (req: Request, res: Response) { export const postReset = function (req: Request, res: Response) { async.waterfall( [ - function (done: any) { + function (done: (args: null, user: DashUserModel) => void) { User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }) - .then((user: any) => { + .then((user: DashUserModel | null) => { if (!user) return res.redirect('back'); check('password', 'Password must be at least 4 characters long').isLength({ min: 4 }).run(req); @@ -250,8 +244,8 @@ export const postReset = function (req: Request, res: Response) { user.save() .then( - () => (req as any).logIn(user), - (err: any) => err + // eslint-disable-next-line @typescript-eslint/no-explicit-any + () => req.logIn(user, (err: any) => err) ) .catch(() => res.redirect('/login')); done(null, user); @@ -259,7 +253,7 @@ export const postReset = function (req: Request, res: Response) { }) .catch(() => res.redirect('back')); }, - function (user: DashUserModel, done: any) { + function (user: DashUserModel, done: (args: null, error: Error | null) => void) { const smtpTransport = nodemailer.createTransport({ service: 'Gmail', auth: { diff --git a/src/server/authentication/DashUserModel.ts b/src/server/authentication/DashUserModel.ts index 6fd8dd593..7aa7f2598 100644 --- a/src/server/authentication/DashUserModel.ts +++ b/src/server/authentication/DashUserModel.ts @@ -3,30 +3,31 @@ import * as mongoose from 'mongoose'; import { Utils } from '../../Utils'; type comparePasswordFunction = (candidatePassword: string, cb: (err: Error, isMatch: boolean) => void) => void; -type mongooseDocument = { id: string }; // & mongoose.Document; -export type DashUserModel = mongooseDocument & { - email: string; - password: string; - passwordResetToken?: string; - passwordResetExpires?: Date; +export type DashUserModel = mongoose.Document & { + email?: string | null | undefined; + password?: string | null | undefined; + passwordResetToken?: string | null | undefined; + passwordResetExpires?: Date | null | undefined; - dropboxRefresh?: string; - dropboxToken?: string; + dropboxRefresh?: string | null | undefined; + dropboxToken?: string | null | undefined; - userDocumentId: string; - sharingDocumentId: string; - linkDatabaseId: string; - cacheDocumentIds: string; + userDocumentId?: string | null | undefined; + sharingDocumentId?: string | null | undefined; + linkDatabaseId?: string | null | undefined; + cacheDocumentIds?: string | null | undefined; + profile?: + | { + name?: string | null | undefined; + gender?: string | null | undefined; + location?: string | null | undefined; + website?: string | null | undefined; + picture?: string | null | undefined; + } + | null + | undefined; - profile: { - name: string; - gender: string; - location: string; - website: string; - picture: string; - }; - - comparePassword: comparePasswordFunction; + comparePassword?: comparePasswordFunction | null | undefined; }; export type AuthToken = { @@ -68,36 +69,38 @@ const userSchema = new mongoose.Schema( */ // eslint-disable-next-line @typescript-eslint/no-explicit-any userSchema.pre('save', function save(next: any) { - const user = this; - if (!user.isModified('password')) { + if (!this.isModified('password')) { return next(); } - bcrypt.genSalt(10, (err: Error, salt: string) => { - if (err) { - return next(err); - } - bcrypt.hash( - user.password ?? '', - salt, - () => {}, - (cryptErr: mongoose.Error, hash: string) => { - if (cryptErr) { - return next(cryptErr); - } - user.password = hash; - next(); - return undefined; + bcrypt.genSalt( + 10, + ((err: Error, salt: string) => { + if (err) { + return next(err); } - ); - return undefined; - }); + bcrypt.hash( + this.password ?? '', + salt, + () => {}, + (cryptErr: mongoose.Error, hash: string) => { + if (cryptErr) { + return next(cryptErr); + } + this.password = hash; + next(); + return undefined; + } + ); + return undefined; + }).bind(this) + ); return undefined; }); const comparePassword: comparePasswordFunction = function (this: DashUserModel, candidatePassword, cb) { // Choose one of the following bodies for authentication logic. // secure (expected, default) - bcrypt.compare(candidatePassword, this.password, cb); + this.password && bcrypt.compare(candidatePassword, this.password, cb); // bypass password (debugging) // cb(undefined, true); }; diff --git a/src/server/authentication/Passport.ts b/src/server/authentication/Passport.ts index a62d38e3e..38a99bd45 100644 --- a/src/server/authentication/Passport.ts +++ b/src/server/authentication/Passport.ts @@ -1,25 +1,28 @@ import * as passport from 'passport'; import * as passportLocal from 'passport-local'; import User, { DashUserModel } from './DashUserModel'; +import { IncomingMessage } from 'webpack-dev-middleware'; const LocalStrategy = passportLocal.Strategy; -passport.serializeUser<any, any>((req, user, done) => { +// eslint-disable-next-line @typescript-eslint/no-explicit-any +passport.serializeUser<any, IncomingMessage & DashUserModel>((req, user, done) => { done(undefined, (user as DashUserModel)?.id); }); -passport.deserializeUser<any, any>((id, done) => { +// eslint-disable-next-line @typescript-eslint/no-explicit-any +passport.deserializeUser<any, IncomingMessage & DashUserModel>((id, done) => { User.findById(id) .exec() - .then((user: DashUserModel) => done(undefined, user)); + .then((user: DashUserModel | null) => user && done(undefined, user)); }); // AUTHENTICATE JUST WITH EMAIL AND PASSWORD passport.use( new LocalStrategy({ usernameField: 'email', passReqToCallback: true }, (req, email, password, done) => { User.findOne({ email: email.toLowerCase() }) - .then((user: DashUserModel) => { - if (!user) { + .then((user: DashUserModel | null) => { + if (!user?.comparePassword) { done(undefined, false, { message: 'Invalid email or password' }); // invalid email } else { user.comparePassword(password, (error: Error, isMatch: boolean) => { |