diff --git a/adminforth/modules/configValidator.ts b/adminforth/modules/configValidator.ts index 0e5d31891..148180f5e 100644 --- a/adminforth/modules/configValidator.ts +++ b/adminforth/modules/configValidator.ts @@ -530,7 +530,6 @@ export default class ConfigValidator implements IConfigValidator { } if (col.foreignResource) { - if (!col.foreignResource.resourceId) { // resourceId is absent or empty if (!col.foreignResource.polymorphicResources && !col.foreignResource.polymorphicOn) { @@ -550,11 +549,11 @@ export default class ConfigValidator implements IConfigValidator { } // we do || here because 'resourceId' might yet not be assigned from 'table' col.foreignResource.polymorphicResources.forEach((polymorphicResource, polymorphicResourceIndex) => { - if (!polymorphicResource.resourceId) { + if (polymorphicResource.resourceId === undefined) { errors.push(`Resource "${res.resourceId}" column "${col.name}" has polymorphic foreign resource without resourceId`); } else if (!polymorphicResource.whenValue) { errors.push(`Resource "${res.resourceId}" column "${col.name}" has polymorphic foreign resource without whenValue`); - } else { + } else if (polymorphicResource.resourceId !== null) { const resource = this.inputConfig.resources.find((r) => r.resourceId === polymorphicResource.resourceId || r.table === polymorphicResource.resourceId); if (!resource) { const similar = suggestIfTypo(this.inputConfig.resources.map((r) => r.resourceId || r.table), polymorphicResource.resourceId); diff --git a/adminforth/modules/restApi.ts b/adminforth/modules/restApi.ts index 8486e5353..0ec1f5b64 100644 --- a/adminforth/modules/restApi.ts +++ b/adminforth/modules/restApi.ts @@ -703,7 +703,14 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI { const targetResourcePkFields = {}; const pksUniques = {}; col.foreignResource.polymorphicResources.forEach((pr) => { - targetResources[pr.whenValue] = this.adminforth.config.resources.find((res) => res.resourceId == pr.resourceId); + if (pr.resourceId === null) { + return; + } + const targetResource = this.adminforth.config.resources.find((res) => res.resourceId == pr.resourceId); + if (!targetResource) { + return; + } + targetResources[pr.whenValue] = targetResource; targetConnectors[pr.whenValue] = this.adminforth.connectors[targetResources[pr.whenValue].dataSource]; targetResourcePkFields[pr.whenValue] = targetResources[pr.whenValue].columns.find((col) => col.primaryKey).name; const pksUnique = [...new Set(data.data.filter((item) => item[col.foreignResource.polymorphicOn] === pr.whenValue).map((item) => item[col.name]))]; @@ -747,6 +754,13 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI { data.data.forEach((item) => { item[col.name] = targetDataMap[item[col.name]]; + + if (!item[col.name]) { + const systemResource = col.foreignResource.polymorphicResources.find(pr => pr.resourceId === null); + if (systemResource) { + item[col.foreignResource.polymorphicOn] = systemResource.whenValue; + } + } }); }) ); @@ -819,7 +833,7 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI { return { error: `Column '${column}' in resource '${resourceId}' is not a foreign key` }; } - const targetResourceIds = columnConfig.foreignResource.resourceId ? [columnConfig.foreignResource.resourceId] : columnConfig.foreignResource.polymorphicResources.map((pr) => pr.resourceId); + const targetResourceIds = columnConfig.foreignResource.resourceId ? [columnConfig.foreignResource.resourceId] : columnConfig.foreignResource.polymorphicResources.filter(pr => pr.resourceId !== null).map((pr) => pr.resourceId); const targetResources = targetResourceIds.map((trId) => this.adminforth.config.resources.find((res) => res.resourceId == trId)); const responses = (await Promise.all( @@ -974,7 +988,14 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI { const targetConnectors = {}; const targetResourcePkFields = {}; column.foreignResource.polymorphicResources.forEach((pr) => { - targetResources[pr.whenValue] = this.adminforth.config.resources.find((res) => res.resourceId == pr.resourceId); + if (pr.resourceId === null) { + return; + } + const targetResource = this.adminforth.config.resources.find((res) => res.resourceId == pr.resourceId); + if (!targetResource) { + return; + } + targetResources[pr.whenValue] = targetResource; targetConnectors[pr.whenValue] = this.adminforth.connectors[targetResources[pr.whenValue].dataSource]; targetResourcePkFields[pr.whenValue] = targetResources[pr.whenValue].columns.find((col) => col.primaryKey).name; }); @@ -1062,7 +1083,14 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI { const targetConnectors = {}; const targetResourcePkFields = {}; column.foreignResource.polymorphicResources.forEach((pr) => { - targetResources[pr.whenValue] = this.adminforth.config.resources.find((res) => res.resourceId == pr.resourceId); + if (pr.resourceId === null) { + return; + } + const targetResource = this.adminforth.config.resources.find((res) => res.resourceId == pr.resourceId); + if (!targetResource) { + return; + } + targetResources[pr.whenValue] = targetResource; targetConnectors[pr.whenValue] = this.adminforth.connectors[targetResources[pr.whenValue].dataSource]; targetResourcePkFields[pr.whenValue] = targetResources[pr.whenValue].columns.find((col) => col.primaryKey).name; }); diff --git a/dev-demo/resources/api_keys.ts b/dev-demo/resources/api_keys.ts index cd055ae8b..429896c81 100644 --- a/dev-demo/resources/api_keys.ts +++ b/dev-demo/resources/api_keys.ts @@ -54,6 +54,10 @@ export default { resourceId: 'providers', whenValue: 'provider', }, + { + resourceId: null, + whenValue: 'Syst1em', + }, ], polymorphicOn: 'owner', },