From 083537ff4bbebe28c89443c02fd1a0d6d973bce3 Mon Sep 17 00:00:00 2001 From: Roman Malenko Date: Wed, 9 Sep 2026 17:27:07 +0300 Subject: [PATCH 1/2] fix: resolve function-valued backendOnly and project the record it returns --- index.ts | 23 +++++++++++++++-------- package.json | 4 ++-- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/index.ts b/index.ts index 1f3d7c9..bbb1da5 100644 --- a/index.ts +++ b/index.ts @@ -1,4 +1,4 @@ -import { AdminForthPlugin, interpretResource, ActionCheckSource, AllowedActionsEnum } from "adminforth"; +import { AdminForthPlugin, interpretResource, ActionCheckSource, AllowedActionsEnum, recordWriteError, stripBackendOnly } from "adminforth"; import type { IAdminForth, IHttpServer, AdminForthResourcePages, AdminForthResourceColumn, AdminForthDataTypes, AdminForthResource } from "adminforth"; import type { PluginOptions } from './types.js'; import { z } from "zod"; @@ -82,12 +82,6 @@ export default class ListInPlaceEditPlugin extends AdminForthPlugin { if (column.primaryKey) { return { error: 'Primary key field cannot be edited' }; } - if (column.backendOnly === true) { - return { error: 'Field is not editable, because it is marked as backendOnly' }; - } - if (column.editReadonly === true) { - return { error: 'Field is not editable, because it is marked as editReadonly' }; - } // Create update object with just the single field const updateRecord = { [field]: value }; @@ -98,12 +92,15 @@ export default class ListInPlaceEditPlugin extends AdminForthPlugin { return { error: 'Record not found' }; } + const editMeta = { requestBody: body, newRecord: updateRecord, oldRecord, pk: recordId }; + const editCtx = { adminUser, resource, meta: editMeta, source: ActionCheckSource.EditRequest, adminforth: this.adminforth }; + // Enforce the resource's edit permission for this specific record // (mirrors the core /update_record access check, since updateResourceRecord does not check ACL). const { allowedActions } = await interpretResource( adminUser, resource, - { requestBody: body, newRecord: updateRecord, oldRecord, pk: recordId }, + editMeta, ActionCheckSource.EditRequest, this.adminforth ); @@ -112,6 +109,11 @@ export default class ListInPlaceEditPlugin extends AdminForthPlugin { return { error: typeof editAllowed === 'string' ? editAllowed : 'You do not have permission to edit this record' }; } + const writeError = await recordWriteError(updateRecord, 'edit', editCtx); + if (writeError) { + return { error: writeError }; + } + const result = await this.adminforth.updateResourceRecord({ resource, recordId, @@ -125,6 +127,11 @@ export default class ListInPlaceEditPlugin extends AdminForthPlugin { } const updatedRecord = await connector.getRecordByPrimaryKey(resource, recordId as string); + if (updatedRecord) { + await stripBackendOnly(updatedRecord, { ...editCtx, meta: { requestBody: body, pk: recordId }, source: ActionCheckSource.EditLoadRequest }); + // _label is not a declared column, so stripBackendOnly would drop it: set it after + updatedRecord._label = resource.recordLabel(updatedRecord); + } return { record: updatedRecord }; } }); diff --git a/package.json b/package.json index d489dd3..663d5b2 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "description": "AdminForth List In Place Edit Plugin", "devDependencies": { "@types/node": "^22.10.7", - "adminforth": "^3.8.2", + "adminforth": "^3.18.0", "semantic-release": "^24.2.1", "semantic-release-slack-bot": "^4.0.2", "typescript": "^5.7.3" @@ -33,7 +33,7 @@ "zod": "^4.3.6" }, "peerDependencies": { - "adminforth": "^3.8.2" + "adminforth": "^3.18.0" }, "release": { "plugins": [ From b1cec8fd0d83d6441c0a49bd2bdbd897a3336ab1 Mon Sep 17 00:00:00 2001 From: Roman Malenko Date: Thu, 10 Sep 2026 08:58:53 +0300 Subject: [PATCH 2/2] fix: stop adding _label to the in-place edit response --- index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/index.ts b/index.ts index bbb1da5..994aeeb 100644 --- a/index.ts +++ b/index.ts @@ -129,8 +129,6 @@ export default class ListInPlaceEditPlugin extends AdminForthPlugin { const updatedRecord = await connector.getRecordByPrimaryKey(resource, recordId as string); if (updatedRecord) { await stripBackendOnly(updatedRecord, { ...editCtx, meta: { requestBody: body, pk: recordId }, source: ActionCheckSource.EditLoadRequest }); - // _label is not a declared column, so stripBackendOnly would drop it: set it after - updatedRecord._label = resource.recordLabel(updatedRecord); } return { record: updatedRecord }; }