Skip to content

Commit cfc02e4

Browse files
committed
refactor: enhance two-factor authentication error messages and clean up save interceptors
1 parent 426d610 commit cfc02e4

File tree

7 files changed

+30
-89
lines changed

7 files changed

+30
-89
lines changed

adminforth/commands/createCustomComponent/templates/customCrud/saveButton.vue.hbs

Lines changed: 0 additions & 28 deletions
This file was deleted.

adminforth/documentation/docs/tutorial/07-Plugins/02-TwoFactorsAuth.md

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -343,11 +343,13 @@ registerSaveInterceptor(async ({ action, values, resource }) => {
343343
const modal = (window as any)?.adminforthTwoFaModal;
344344
if (modal?.get2FaConfirmationResult) {
345345
const confirmationResult = await modal.get2FaConfirmationResult(undefined, 'Confirm to save changes');
346-
if (!confirmationResult) return { ok: false, error: '2FA cancelled' };
346+
if (!confirmationResult) {
347+
return { ok: false, error: 'Two-factor authentication cancelled' };
348+
}
347349
// Pass data to backend; the view will forward extra.confirmationResult to meta.confirmationResult
348350
return { ok: true, extra: { confirmationResult } };
349351
}
350-
return { ok: false, error: '2FA code is required' };
352+
return { ok: false, error: 'Two-factor authentication code is required' };
351353
});
352354
</script>
353355

@@ -364,7 +366,7 @@ options: {
364366
}
365367
}
366368
```
367-
> Note: You can use all injection, not only bottom
369+
> Note: You can use all injections, not only bottom
368370
369371
Backend (resource hook verification):
370372
@@ -374,27 +376,34 @@ hooks: {
374376
edit: {
375377
beforeSave: async ({ adminUser, adminforth, extra }) => {
376378
const t2fa = adminforth.getPluginByClassName('TwoFactorsAuthPlugin');
377-
const confirmationResult = extra?.body?.meta?.confirmationResult;
379+
if (!t2fa) {
380+
return { ok: false, error: 'TwoFactorsAuthPlugin is not configured' };
381+
}
378382

383+
const confirmationResult = extra?.body?.meta?.confirmationResult;
379384
if (!confirmationResult) {
380385
return { ok: false, error: 'Two-factor authentication confirmation result is missing' };
381386
}
387+
382388
const verifyRes = await t2fa.verify(confirmationResult, {
383389
adminUser,
384390
userPk: adminUser.pk,
385391
cookies: extra?.cookies,
386392
});
387393
if (!verifyRes || 'error' in verifyRes) {
388-
return { ok: false, error: verifyRes?.error || '2FA verification failed' };
394+
return { ok: false, error: verifyRes?.error || 'Two-factor verification failed' };
389395
}
390396
return { ok: true };
391397
},
392398
},
393399
create: {
394400
beforeSave: async ({ adminUser, adminforth, extra }) => {
395401
const t2fa = adminforth.getPluginByClassName('TwoFactorsAuthPlugin');
396-
const confirmationResult = extra?.body?.meta?.confirmationResult;
402+
if (!t2fa) {
403+
return { ok: false, error: 'TwoFactorsAuthPlugin is not configured' };
404+
}
397405

406+
const confirmationResult = extra?.body?.meta?.confirmationResult;
398407
if (!confirmationResult) {
399408
return { ok: false, error: 'Two-factor authentication confirmation result is missing' };
400409
}
@@ -405,7 +414,7 @@ hooks: {
405414
cookies: extra?.cookies,
406415
});
407416
if (!verifyRes || 'error' in verifyRes) {
408-
return { ok: false, error: verifyRes?.error || '2FA verification failed' };
417+
return { ok: false, error: verifyRes?.error || 'Two-factor verification failed' };
409418
}
410419
return { ok: true };
411420
},

adminforth/spa/src/adminforth.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class FrontendAPI implements FrontendAPIInterface {
9898
this.saveInterceptors[rid].push(handler);
9999
}
100100

101-
async runSaveInterceptors(params: { action: 'create'|'edit'; values: any; resource: any; resourceId: string; }): Promise<{ ok: boolean; error?: string | null; extra?: any }>{
101+
async runSaveInterceptors(params: { action: 'create'|'edit'; values: any; resource: any; resourceId: string; }): Promise<{ ok: boolean; error?: string | null; extra?: object; }> {
102102
const list = this.saveInterceptors[params.resourceId] || [];
103103
const aggregatedExtra: Record<string, any> = {};
104104
for (const fn of list) {
@@ -227,7 +227,7 @@ export function initFrontedAPI() {
227227
export function useAdminforth() {
228228
const api = frontendAPI as FrontendAPI;
229229
return {
230-
registerSaveInterceptor: (handler: (ctx: { action: 'create'|'edit'; values: any; resource: any; resourceId: string; }) => Promise<{ ok: boolean; error?: string | null; }>, resourceId?: string) => api.registerSaveInterceptor(handler, resourceId),
230+
registerSaveInterceptor: (handler: (ctx: { action: 'create'|'edit'; values: any; resource: any; }) => Promise<{ ok: boolean; error?: string | null; extra?: object; }>) => api.registerSaveInterceptor(handler),
231231
runSaveInterceptors: (params: { action: 'create'|'edit'; values: any; resource: any; resourceId: string; }) => api.runSaveInterceptors(params),
232232
clearSaveInterceptors: (resourceId?: string) => api.clearSaveInterceptors(resourceId),
233233
api,

adminforth/spa/src/views/CreateView.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ async function saveRecord() {
186186
if (interceptorsResult.error) showErrorTost(interceptorsResult.error);
187187
return;
188188
}
189-
const interceptorConfirmationResult = interceptorsResult?.extra?.confirmationResult;
189+
const interceptorConfirmationResult = interceptorsResult.extra?.confirmationResult;
190190
const response = await callAdminForthApi({
191191
method: 'POST',
192192
path: `/create_record`,

adminforth/spa/src/views/EditView.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ async function saveRecord() {
176176
if (interceptorsResult.error) showErrorTost(interceptorsResult.error);
177177
return;
178178
}
179-
const interceptorConfirmationResult = interceptorsResult?.extra?.confirmationResult;
179+
const interceptorConfirmationResult = interceptorsResult.extra?.confirmationResult;
180180
const updates: Record<string, any> = {};
181181
for (const key in record.value) {
182182
let columnIsUpdated = false;

dev-demo/custom/SaveInterceptor.vue

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ const { registerSaveInterceptor } = useAdminforth()
66
registerSaveInterceptor(async ({ action, values, resource }) => {
77
console.log('Custom Save Interceptor triggered:', { action, values, resource });
88
const modal = window?.adminforthTwoFaModal;
9-
if (modal?.get2FaConfirmationResult) {
10-
const confirmationResult = await modal.get2FaConfirmationResult(
11-
undefined,
12-
'Confirm to save changes'
13-
);
14-
return { ok: true, extra: { confirmationResult } };
15-
} else {
16-
return { ok: false, error: '2FA code is required' }
17-
}
9+
if (modal?.get2FaConfirmationResult) {
10+
const confirmationResult = await modal.get2FaConfirmationResult(
11+
undefined,
12+
'Confirm to save changes'
13+
);
14+
return { ok: true, extra: { confirmationResult } };
15+
} else {
16+
return { ok: false, error: '2FA code is required' }
17+
}
1818
})
1919
</script>
2020

dev-demo/resources/cars_mongo.ts

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -327,14 +327,6 @@ export default {
327327
328328
329329
*********************************************************************************/
330-
hooks: {
331-
edit: {
332-
beforeSave: async ({ adminUser, adminforth, extra }) => verifyTwoFa({ adminUser, adminforth, extra }),
333-
},
334-
create: {
335-
beforeSave: async ({ adminUser, adminforth, extra }) => verifyTwoFa({ adminUser, adminforth, extra }),
336-
},
337-
},
338330
options: {
339331
listPageSize: 12,
340332
allowedActions: {
@@ -343,20 +335,6 @@ export default {
343335
show: true,
344336
filter: true,
345337
},
346-
pageInjections: {
347-
edit: {
348-
bottom: [
349-
{ file: '@@/SaveInterceptor.vue' },
350-
{ file: '@@/SaveInterceptorExtra.vue' },
351-
],
352-
},
353-
create: {
354-
bottom: [
355-
{ file: '@@/SaveInterceptor.vue' },
356-
{ file: '@@/SaveInterceptorExtra.vue' },
357-
],
358-
},
359-
},
360338
actions: [
361339
{
362340
name: 'Approve Listing',
@@ -408,22 +386,4 @@ export default {
408386
}
409387
],
410388
},
411-
} as AdminForthResourceInput;
412-
413-
async function verifyTwoFa({ adminUser, adminforth, extra }: { adminUser: any, adminforth: any, extra: any }) {
414-
const t2fa = adminforth.getPluginByClassName('TwoFactorsAuthPlugin');
415-
const confirmationResult = extra?.body?.meta?.confirmationResult;
416-
417-
if (!confirmationResult) {
418-
return { ok: false, error: 'Two-factor authentication confirmation result is missing' };
419-
}
420-
const verifyRes = await t2fa.verify(confirmationResult, {
421-
adminUser,
422-
userPk: adminUser.pk,
423-
cookies: extra?.cookies,
424-
});
425-
if (!verifyRes || 'error' in verifyRes) {
426-
return { ok: false, error: verifyRes?.error || '2FA verification failed' };
427-
}
428-
return { ok: true };
429-
}
389+
} as AdminForthResourceInput;

0 commit comments

Comments
 (0)