1- import { AdminForthPlugin , Filters } from "adminforth" ;
1+ import { AdminForthPlugin , Filters , suggestIfTypo } from "adminforth" ;
22import type { AdminForthResource , AdminUser , IAdminForth , IHttpServer , IAdminForthAuth , BeforeLoginConfirmationFunction , IAdminForthHttpResponse } from "adminforth" ;
33import twofactor from 'node-2fa' ;
44import { PluginOptions } from "./types.js"
@@ -173,9 +173,36 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
173173 if ( ! this . options . passkeys . credentialIdFieldName ) {
174174 throw new Error ( 'Passkeys credentialIdFieldName is required' ) ;
175175 }
176+
177+ const credentialResource = adminforth . config . resources . find ( r => r . resourceId === this . options . passkeys . credentialResourceID ) ;
178+ const credentialIDField = credentialResource . columns . find ( c => c . name === this . options . passkeys . credentialIdFieldName ) ;
179+ if ( ! credentialIDField ) {
180+ const similar = suggestIfTypo ( credentialResource . columns . map ( c => c . name ) , this . options . passkeys . credentialIdFieldName ) ;
181+ throw new Error (
182+ `Passkeys credentialIdFieldName '${ this . options . passkeys . credentialIdFieldName } ' not found in resource '${ this . options . passkeys . credentialResourceID } '. ${
183+ similar ? `Did you mean '${ similar } '?` : ''
184+ } `
185+ ) ;
186+ }
187+ credentialIDField . backendOnly = true ;
188+
176189 if ( ! this . options . passkeys . credentialMetaFieldName ) {
177190 throw new Error ( 'Passkeys credentialMetaFieldName is required' ) ;
178191 }
192+
193+ const metaResource = adminforth . config . resources . find ( r => r . resourceId === this . options . passkeys . credentialMetaFieldName ) ;
194+ const metaField = credentialResource . columns . find ( c => c . name === this . options . passkeys . credentialMetaFieldName ) ;
195+ if ( ! metaField ) {
196+ const similar = suggestIfTypo ( metaResource . columns . map ( c => c . name ) , this . options . passkeys . credentialMetaFieldName ) ;
197+ throw new Error (
198+ `Passkeys credentialMetaFieldName '${ this . options . passkeys . credentialMetaFieldName } ' not found in resource '${ this . options . passkeys . credentialMetaFieldName } '. ${
199+ similar ? `Did you mean '${ similar } '?` : ''
200+ } `
201+ ) ;
202+ }
203+ metaField . backendOnly = true ;
204+
205+
179206 if ( ! this . options . passkeys . credentialUserIdFieldName ) {
180207 throw new Error ( 'Passkeys credentialUserIdFieldName is required' ) ;
181208 }
@@ -455,7 +482,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
455482 userVerification : this . options . passkeys ?. settings . authenticatorSelection . userVerification || "required"
456483 } ,
457484 } ) ;
458- const value = this . adminforth . auth . issueJWT ( { "challenge" : options . challenge , "user_id" : adminUser . pk } , 'tempPasskeyChallenge ' , '10m' ) ;
485+ const value = this . adminforth . auth . issueJWT ( { "challenge" : options . challenge , "user_id" : adminUser . pk } , 'registerTempPasskeyChallenge ' , '10m' ) ;
459486 this . adminforth . auth . setCustomCookie ( { response, payload : { name : "registerPasskeyTemporaryJWT" , value : value , expiry : undefined , expirySeconds : 10 * 60 , httpOnly : true } } ) ;
460487 return { ok : true , data : options } ;
461488 }
@@ -469,7 +496,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
469496 if ( ! passkeysCookies ) {
470497 return { error : 'Passkey token is required' } ;
471498 }
472- const decodedPasskeysCookies = await this . adminforth . auth . verify ( passkeysCookies , 'tempPasskeyChallenge ' , false ) ;
499+ const decodedPasskeysCookies = await this . adminforth . auth . verify ( passkeysCookies , 'registerTempPasskeyChallenge ' , false ) ;
473500 if ( ! decodedPasskeysCookies ) {
474501 return { error : 'Invalid passkey token' } ;
475502 }
@@ -584,12 +611,12 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
584611 path : `/plugin/passkeys/deletePasskey` ,
585612 noAuth : false ,
586613 handler : async ( { body, adminUser } ) => {
587- const passkeyId = body . passkeyId ;
588- if ( ! passkeyId ) {
614+ const credentialID = body . passkeyId ;
615+ if ( ! credentialID ) {
589616 return { ok : false , error : 'Passkey ID is required' } ;
590617 }
591618
592- const passkeyRecord = await this . adminforth . resource ( this . options . passkeys . credentialResourceID ) . get ( [ Filters . EQ ( this . options . passkeys . credentialIdFieldName , passkeyId ) , Filters . EQ ( this . options . passkeys . credentialUserIdFieldName , adminUser . pk ) ] ) ;
619+ const passkeyRecord = await this . adminforth . resource ( this . options . passkeys . credentialResourceID ) . get ( [ Filters . EQ ( this . options . passkeys . credentialIdFieldName , credentialID ) , Filters . EQ ( this . options . passkeys . credentialUserIdFieldName , adminUser . pk ) ] ) ;
593620 if ( ! passkeyRecord ) {
594621 return { ok : false , error : 'Passkey not found' } ;
595622 }
@@ -598,9 +625,18 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
598625 if ( ! credResource ) {
599626 throw new Error ( 'Credential resource not found.' ) ;
600627 }
628+ const credResourcePKColumn = credResource . columns . find ( c => c . primaryKey ) ;
629+ if ( ! credResourcePKColumn ) {
630+ throw new Error ( 'Credential resource primary key not found.' ) ;
631+ }
632+ const credResourcePKName = credResourcePKColumn . name ;
633+ const passkeyRecord = await this . adminforth . resource ( this . options . passkeys . credentialResourceID ) . get ( [ Filters . EQ ( this . options . passkeys . credentialIdFieldName , credentialID ) , Filters . EQ ( this . options . passkeys . credentialUserIdFieldName , adminUser . pk ) ] ) ;
634+ if ( ! passkeyRecord ) {
635+ return { ok : false , error : 'Passkey not found' } ;
636+ }
601637 await this . adminforth . deleteResourceRecord ( {
602638 resource : credResource ,
603- recordId : passkeyId ,
639+ recordId : passkeyRecord [ credResourcePKName ] ,
604640 record : passkeyRecord ,
605641 adminUser : adminUser ,
606642 } ) ;
@@ -616,16 +652,24 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
616652 path : `/plugin/passkeys/renamePasskey` ,
617653 noAuth : false ,
618654 handler : async ( { body, adminUser } ) => {
619- const passkeyId = body . passkeyId ;
655+ const credentialID = body . passkeyId ;
620656 const newName = body . newName ;
621- if ( ! passkeyId ) {
657+ if ( ! credentialID ) {
622658 return { ok : false , error : 'Passkey ID is required' } ;
623659 }
624660 if ( ! newName ) {
625661 return { ok : false , error : 'New name is required' } ;
626662 }
627-
628- const passkeyRecord = await this . adminforth . resource ( this . options . passkeys . credentialResourceID ) . get ( [ Filters . EQ ( this . options . passkeys . credentialIdFieldName , passkeyId ) , Filters . EQ ( this . options . passkeys . credentialUserIdFieldName , adminUser . pk ) ] ) ;
663+ const credResource = this . adminforth . config . resources . find ( r => r . resourceId === this . options . passkeys . credentialResourceID ) ;
664+ if ( ! credResource ) {
665+ throw new Error ( 'Credential resource not found.' ) ;
666+ }
667+ const credResourcePKColumn = credResource . columns . find ( c => c . primaryKey ) ;
668+ if ( ! credResourcePKColumn ) {
669+ throw new Error ( 'Credential resource primary key not found.' ) ;
670+ }
671+ const credResourcePKName = credResourcePKColumn . name ;
672+ const passkeyRecord = await this . adminforth . resource ( this . options . passkeys . credentialResourceID ) . get ( [ Filters . EQ ( this . options . passkeys . credentialIdFieldName , credentialID ) , Filters . EQ ( this . options . passkeys . credentialUserIdFieldName , adminUser . pk ) ] ) ;
629673 if ( ! passkeyRecord ) {
630674 return { ok : false , error : 'Passkey not found' } ;
631675 }
@@ -639,7 +683,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
639683 }
640684 await this . adminforth . updateResourceRecord ( {
641685 resource : credResource ,
642- recordId : passkeyId ,
686+ recordId : passkeyRecord [ credResourcePKName ] ,
643687 oldRecord : passkeyRecord ,
644688 record : newRecord ,
645689 adminUser : adminUser
0 commit comments