From 827c56735098280660f070f185fdf9af2dbdac54 Mon Sep 17 00:00:00 2001 From: Javad Mnjd Date: Sun, 31 Mar 2024 22:35:37 +0330 Subject: [PATCH 1/3] fix: improve typescript types --- src/helpers/hash-password.ts | 2 +- src/helpers/typescript.ts | 3 +++ src/methods/check-unique.ts | 7 ++++--- src/methods/reset-password.ts | 3 ++- src/methods/verify-signup-set-password.ts | 3 ++- src/methods/verify-signup.ts | 3 ++- src/services/AuthenticationManagementBase.ts | 5 +++-- src/types.ts | 2 +- tsconfig.json | 1 + 9 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 src/helpers/typescript.ts diff --git a/src/helpers/hash-password.ts b/src/helpers/hash-password.ts index 4cd121f..a4501cc 100644 --- a/src/helpers/hash-password.ts +++ b/src/helpers/hash-password.ts @@ -7,7 +7,7 @@ export async function hashPassword ( field: string ): Promise { if (!field) throw new Error('Field is missing'); - const context = { + const context: Partial = { type: 'before', data: { [field]: password }, params: { provider: null }, diff --git a/src/helpers/typescript.ts b/src/helpers/typescript.ts new file mode 100644 index 0000000..83d0916 --- /dev/null +++ b/src/helpers/typescript.ts @@ -0,0 +1,3 @@ +export function typedObjectKeys(o: T): Array { + return Object.keys(o) as Array; +} diff --git a/src/methods/check-unique.ts b/src/methods/check-unique.ts index a239dc6..eb68d9a 100644 --- a/src/methods/check-unique.ts +++ b/src/methods/check-unique.ts @@ -1,6 +1,7 @@ import { BadRequest } from '@feathersjs/errors'; import makeDebug from 'debug'; +import { typedObjectKeys } from '../helpers/typescript'; import type { NullableId, Params } from '@feathersjs/feathers'; import type { CheckUniqueOptions, @@ -36,7 +37,7 @@ export default async function checkUnique ( const usersServiceId = usersService.id; const errProps = []; - const keys = Object.keys(identifyUser).filter( + const keys = typedObjectKeys(identifyUser).filter( key => identifyUser[key] != null ); @@ -67,8 +68,8 @@ export default async function checkUnique ( } if (errProps.length) { - const errs = {}; - errProps.forEach(prop => { errs[prop] = 'Already taken.'; }); + const errs: Record = {}; + errProps.forEach((prop ) => { errs[prop] = 'Already taken.'; }); throw new BadRequest( meta?.noErrMsg ? null : 'Values already taken.', diff --git a/src/methods/reset-password.ts b/src/methods/reset-password.ts index 2cc3cf3..30152f0 100644 --- a/src/methods/reset-password.ts +++ b/src/methods/reset-password.ts @@ -9,6 +9,7 @@ import { hashPassword, notify } from '../helpers'; +import { typedObjectKeys } from '../helpers/typescript'; import type { Id, Params } from '@feathersjs/feathers'; import type { @@ -114,7 +115,7 @@ async function resetPassword ( const user = getUserData(users, checkProps); // compare all tokens (hashed) - const tokenChecks = Object.keys(tokens).map(async key => { + const tokenChecks = typedObjectKeys(tokens).map(async key => { if (reuseResetToken) { // Comparing token directly as reused resetToken is not hashed if (tokens[key] !== user[key]) { diff --git a/src/methods/verify-signup-set-password.ts b/src/methods/verify-signup-set-password.ts index 4fe8032..91a9341 100644 --- a/src/methods/verify-signup-set-password.ts +++ b/src/methods/verify-signup-set-password.ts @@ -8,6 +8,7 @@ import { isDateAfterNow, notify } from '../helpers'; +import { typedObjectKeys } from '../helpers/typescript'; import type { Id, Params } from '@feathersjs/feathers'; import type { VerifyChanges } from '..'; @@ -103,7 +104,7 @@ async function verifySignupSetPassword ( 'verifyNotExpired' ]); - if (!Object.keys(tokens).every((key) => tokens[key] === user[key])) { + if (!typedObjectKeys(tokens).every((key) => tokens[key] === user[key])) { await eraseVerifyProps(user, user.isVerified, params); throw new BadRequest( diff --git a/src/methods/verify-signup.ts b/src/methods/verify-signup.ts index eec904d..139bcbd 100644 --- a/src/methods/verify-signup.ts +++ b/src/methods/verify-signup.ts @@ -7,6 +7,7 @@ import { notify, isDateAfterNow } from '../helpers'; +import { typedObjectKeys } from '../helpers/typescript'; import type { Id, Params } from '@feathersjs/feathers'; import type { @@ -98,7 +99,7 @@ async function verifySignup ( let userErasedVerify: User; - if (!Object.keys(tokens).every(key => tokens[key] === user[key])) { + if (!typedObjectKeys(tokens).every((key) => tokens[key] === user[key])) { userErasedVerify = await eraseVerifyProps(user, user.isVerified); throw new BadRequest( diff --git a/src/services/AuthenticationManagementBase.ts b/src/services/AuthenticationManagementBase.ts index 09a9993..bafbdd6 100644 --- a/src/services/AuthenticationManagementBase.ts +++ b/src/services/AuthenticationManagementBase.ts @@ -1,8 +1,9 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { MethodNotAllowed } from '@feathersjs/errors'; import type { Application, Params } from '@feathersjs/feathers'; export abstract class AuthenticationManagementBase { - publish: unknown; + publish: undefined | ((fn: ((...any: any[]) => unknown)) => void); app: Application; options: O; @@ -31,7 +32,7 @@ export abstract class AuthenticationManagementBase { } async setup (): Promise { - if (typeof this.publish === 'function') { + if (typeof this.publish === 'function') { this.publish(() => null); } } diff --git a/src/types.ts b/src/types.ts index a77fecc..d747342 100644 --- a/src/types.ts +++ b/src/types.ts @@ -116,7 +116,7 @@ export interface AuthenticationManagementServiceOptions { * @default 'password' */ passwordField: string /** Pass params from f-a-m service to `/users` service */ - passParams: (params) => Params | Promise + passParams: (params: any) => Params | Promise } export type AuthenticationManagementSetupOptions = AuthenticationManagementServiceOptions & { path: string }; diff --git a/tsconfig.json b/tsconfig.json index b0bc86a..d0f0fe3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,6 +10,7 @@ "sourceMap": false, "declaration": true, "strictNullChecks": false, + "noImplicitAny": true, }, "include": [ "src/**/*" From 361f10fc7e7fe48f12f72c42aedf8d8f26b22b66 Mon Sep 17 00:00:00 2001 From: Javad Mnjd Date: Sun, 31 Mar 2024 22:56:16 +0330 Subject: [PATCH 2/3] fix: more type issues --- src/client.ts | 6 +++--- src/helpers/sanitize-user-for-client.ts | 2 +- src/helpers/sanitize-user-for-notifier.ts | 2 +- src/hooks/add-verification.ts | 2 +- src/methods/check-unique.ts | 2 +- src/methods/identity-change.ts | 2 +- src/methods/password-change.ts | 2 +- src/methods/resend-verify-signup.ts | 4 ++-- src/methods/reset-password.ts | 4 ++-- src/methods/send-reset-pwd.ts | 2 +- src/methods/verify-signup-set-password.ts | 2 +- src/methods/verify-signup.ts | 2 +- src/options.ts | 2 +- src/services/AuthenticationManagementBase.ts | 2 ++ src/types.ts | 2 +- 15 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/client.ts b/src/client.ts index e80b148..f6915b3 100644 --- a/src/client.ts +++ b/src/client.ts @@ -33,7 +33,7 @@ function makeClient (app: Application, _options?: Partial): Authe const authManagement = app.service(path); const client: AuthenticationManagementClient = { - checkUnique: async (identifyUser: IdentifyUser, ownId: NullableId, ifErrMsg?: boolean) => { + checkUnique: async (identifyUser: IdentifyUser, ownId?: NullableId, ifErrMsg?: boolean) => { await authManagement.create({ action: 'checkUnique', value: identifyUser, @@ -129,7 +129,7 @@ function makeClient (app: Application, _options?: Partial): Authe try { if (!user || !user.isVerified) { await app.logout(); - return cb(new Error(user ? 'User\'s email is not verified.' : 'No user returned.')); + return cb && cb(new Error(user ? 'User\'s email is not verified.' : 'No user returned.')); } if (cb) { @@ -140,7 +140,7 @@ function makeClient (app: Application, _options?: Partial): Authe return user; } catch (err) { if (!cbCalled && cb) { - cb(err); + cb(err as Error); } } } diff --git a/src/helpers/sanitize-user-for-client.ts b/src/helpers/sanitize-user-for-client.ts index 1fde79b..3e56fd6 100644 --- a/src/helpers/sanitize-user-for-client.ts +++ b/src/helpers/sanitize-user-for-client.ts @@ -2,7 +2,7 @@ import { cloneObject } from './clone-object'; import type { User } from '../types'; export function sanitizeUserForClient ( - _user: User + _user: Partial ): Record { const user = cloneObject(_user); diff --git a/src/helpers/sanitize-user-for-notifier.ts b/src/helpers/sanitize-user-for-notifier.ts index f0ef31c..e89f0c5 100644 --- a/src/helpers/sanitize-user-for-notifier.ts +++ b/src/helpers/sanitize-user-for-notifier.ts @@ -1,7 +1,7 @@ import { cloneObject } from './clone-object'; import type { User } from '../types'; -export function sanitizeUserForNotifier (_user: User): Record { +export function sanitizeUserForNotifier (_user: Partial): Record { const user = cloneObject(_user); delete user.password; return user; diff --git a/src/hooks/add-verification.ts b/src/hooks/add-verification.ts index e2b3abe..e517004 100644 --- a/src/hooks/add-verification.ts +++ b/src/hooks/add-verification.ts @@ -56,7 +56,7 @@ export function addVerification ( return context; } catch (err) { - throw new GeneralError(err); + throw new GeneralError(err?.message); } }; } diff --git a/src/methods/check-unique.ts b/src/methods/check-unique.ts index eb68d9a..8a218a1 100644 --- a/src/methods/check-unique.ts +++ b/src/methods/check-unique.ts @@ -34,7 +34,7 @@ export default async function checkUnique ( } = options; const usersService = app.service(service); - const usersServiceId = usersService.id; + const usersServiceId = usersService.id!; const errProps = []; const keys = typedObjectKeys(identifyUser).filter( diff --git a/src/methods/identity-change.ts b/src/methods/identity-change.ts index 1f2d632..2f2e746 100644 --- a/src/methods/identity-change.ts +++ b/src/methods/identity-change.ts @@ -31,7 +31,7 @@ export default async function identityChange ( } const usersService = options.app.service(options.service); - const usersServiceId = usersService.id; + const usersServiceId = usersService.id!; const { delay, identifyUserProps, diff --git a/src/methods/password-change.ts b/src/methods/password-change.ts index cd76e94..14acea0 100644 --- a/src/methods/password-change.ts +++ b/src/methods/password-change.ts @@ -46,7 +46,7 @@ export default async function passwordChange ( } = options; const usersService = app.service(service); - const usersServiceId = usersService.id; + const usersServiceId = usersService.id!; ensureValuesAreStrings(oldPassword, password); ensureObjPropsValid(identifyUser, identifyUserProps); diff --git a/src/methods/resend-verify-signup.ts b/src/methods/resend-verify-signup.ts index fa3e9ca..6dde4d9 100644 --- a/src/methods/resend-verify-signup.ts +++ b/src/methods/resend-verify-signup.ts @@ -23,7 +23,7 @@ const debug = makeDebug('authLocalMgnt:resendVerifySignup'); export default async function resendVerifySignup ( options: ResendVerifySignupOptions, identifyUser: IdentifyUser, - notifierOptions: NotifierOptions, + notifierOptions?: NotifierOptions, params?: Params ): Promise { debug('identifyUser=', identifyUser); @@ -46,7 +46,7 @@ export default async function resendVerifySignup ( } = options; const usersService = app.service(service); - const usersServiceId = usersService.id; + const usersServiceId = usersService.id!; ensureObjPropsValid(identifyUser, identifyUserProps.concat('verifyToken', 'verifyShortToken') diff --git a/src/methods/reset-password.ts b/src/methods/reset-password.ts index 30152f0..06cfe8e 100644 --- a/src/methods/reset-password.ts +++ b/src/methods/reset-password.ts @@ -91,7 +91,7 @@ async function resetPassword ( } = options; const usersService = app.service(service); - const usersServiceId = usersService.id; + const usersServiceId = usersService.id!; let users; if (tokens.resetToken) { @@ -125,7 +125,7 @@ async function resetPassword ( } } else { return await comparePasswords( - tokens[key], + tokens[key]!, user[key] as string, () => new BadRequest( diff --git a/src/methods/send-reset-pwd.ts b/src/methods/send-reset-pwd.ts index fca976b..fd0b5e4 100644 --- a/src/methods/send-reset-pwd.ts +++ b/src/methods/send-reset-pwd.ts @@ -51,7 +51,7 @@ export default async function sendResetPwd ( } = options; const usersService = app.service(service); - const usersServiceId = usersService.id; + const usersServiceId = usersService.id!; ensureObjPropsValid(identifyUser, identifyUserProps); diff --git a/src/methods/verify-signup-set-password.ts b/src/methods/verify-signup-set-password.ts index 91a9341..afbecea 100644 --- a/src/methods/verify-signup-set-password.ts +++ b/src/methods/verify-signup-set-password.ts @@ -92,7 +92,7 @@ async function verifySignupSetPassword ( } = options; const usersService = app.service(service); - const usersServiceId = usersService.id; + const usersServiceId = usersService.id!; const users = await usersService.find({ ...params, diff --git a/src/methods/verify-signup.ts b/src/methods/verify-signup.ts index 139bcbd..ab4b74a 100644 --- a/src/methods/verify-signup.ts +++ b/src/methods/verify-signup.ts @@ -83,7 +83,7 @@ async function verifySignup ( } = options; const usersService = app.service(service); - const usersServiceId = usersService.id; + const usersServiceId = usersService.id!; const users = await usersService.find( { diff --git a/src/options.ts b/src/options.ts index 0b1db37..334695d 100644 --- a/src/options.ts +++ b/src/options.ts @@ -14,7 +14,7 @@ export const defaultPath = 'authManagement'; export const optionsDefault: AuthenticationManagementServiceOptions = { service: '/users', // need exactly this for test suite // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function - notifier: async (type: NotificationType, user: User, notifierOptions) => {}, + notifier: async (type: NotificationType, user: Partial, notifierOptions) => {}, longTokenLen: 15, // token's length will be twice this shortTokenLen: 6, shortTokenDigits: true, diff --git a/src/services/AuthenticationManagementBase.ts b/src/services/AuthenticationManagementBase.ts index bafbdd6..6be13c9 100644 --- a/src/services/AuthenticationManagementBase.ts +++ b/src/services/AuthenticationManagementBase.ts @@ -5,6 +5,8 @@ import type { Application, Params } from '@feathersjs/feathers'; export abstract class AuthenticationManagementBase { publish: undefined | ((fn: ((...any: any[]) => unknown)) => void); app: Application; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore not defined in constructor but is used. options: O; abstract _create (data: T, params?: Params): Promise; diff --git a/src/types.ts b/src/types.ts index d747342..6981094 100644 --- a/src/types.ts +++ b/src/types.ts @@ -116,7 +116,7 @@ export interface AuthenticationManagementServiceOptions { * @default 'password' */ passwordField: string /** Pass params from f-a-m service to `/users` service */ - passParams: (params: any) => Params | Promise + passParams?: (params: any) => Params | Promise } export type AuthenticationManagementSetupOptions = AuthenticationManagementServiceOptions & { path: string }; From be8bf26bd74a531d1a8bfbb06f4f205739e4be17 Mon Sep 17 00:00:00 2001 From: Javad Mnjd Date: Sun, 31 Mar 2024 23:01:18 +0330 Subject: [PATCH 3/3] fix: update more types --- src/hooks/add-verification.ts | 3 ++- src/hooks/remove-verification.ts | 4 ++-- src/methods/check-unique.ts | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/hooks/add-verification.ts b/src/hooks/add-verification.ts index e517004..7ab4892 100644 --- a/src/hooks/add-verification.ts +++ b/src/hooks/add-verification.ts @@ -55,7 +55,8 @@ export function addVerification ( ); return context; - } catch (err) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (err: any) { throw new GeneralError(err?.message); } }; diff --git a/src/hooks/remove-verification.ts b/src/hooks/remove-verification.ts index 2e9555e..584e01f 100644 --- a/src/hooks/remove-verification.ts +++ b/src/hooks/remove-verification.ts @@ -12,8 +12,8 @@ export function removeVerification ( return (context: H): H => { checkContext(context, 'after'); // Retrieve the items from the hook - const items: User | User[] = getItems(context); - if (!items) return; + const items: Partial | Partial[] = getItems(context); + if (!items) return context; const isArray = Array.isArray(items); const users = (isArray ? items : [items]); diff --git a/src/methods/check-unique.ts b/src/methods/check-unique.ts index 8a218a1..6366703 100644 --- a/src/methods/check-unique.ts +++ b/src/methods/check-unique.ts @@ -60,10 +60,11 @@ export default async function checkUnique ( errProps.push(prop); } } - } catch (err) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (err: any) { throw new BadRequest( meta?.noErrMsg ? null : 'checkUnique unexpected error.', - { errors: { msg: err.message, $className: 'unexpected' } } + { errors: { msg: err?.message, $className: 'unexpected' } } ); }