fix(selectors): add missing context fields to resolution, ensureCredential to sharepoint.lists, and siteId validation

- Add baseId, datasetId, serviceDeskId to SelectorResolutionArgs,
  ExtendedSelectorContext, extractExtendedContext, useSelectorDisplayName,
  and resolveSelectorForSubBlock so cascading selectors resolve correctly
  through the resolution path.
- Add ensureCredential guard to sharepoint.lists registry entry.
- Add regex validation for SharePoint siteId format (hostname,GUID,GUID).
This commit is contained in:
Waleed Latif
2026-03-05 19:18:07 -08:00
parent a6e695af4e
commit c2041afe9c
5 changed files with 39 additions and 2 deletions
@@ -46,6 +46,11 @@ export async function GET(request: NextRequest) {
return NextResponse.json({ error: 'Site ID is required' }, { status: 400 })
}
const SITE_ID_RE = /^[\w.\-,]+$/
if (siteId.length > 512 || !SITE_ID_RE.test(siteId)) {
return NextResponse.json({ error: 'Invalid site ID format' }, { status: 400 })
}
const credentialIdValidation = validateAlphanumericId(credentialId, 'credentialId', 255)
if (!credentialIdValidation.isValid) {
logger.warn(`[${requestId}] Invalid credential ID`, { error: credentialIdValidation.error })
+4 -2
View File
@@ -721,10 +721,11 @@ const registry: Record<SelectorKey, SelectorDefinition> = {
],
enabled: ({ context }) => Boolean(context.credentialId && context.siteId),
fetchList: async ({ context }: SelectorQueryArgs) => {
const credentialId = ensureCredential(context, 'sharepoint.lists')
if (!context.siteId) throw new Error('Missing site ID for sharepoint.lists selector')
const data = await fetchJson<{ lists: SharepointList[] }>('/api/tools/sharepoint/lists', {
searchParams: {
credentialId: context.credentialId,
credentialId,
siteId: context.siteId,
},
})
@@ -732,9 +733,10 @@ const registry: Record<SelectorKey, SelectorDefinition> = {
},
fetchById: async ({ context, detailId }: SelectorQueryArgs) => {
if (!detailId || !context.siteId) return null
const credentialId = ensureCredential(context, 'sharepoint.lists')
const data = await fetchJson<{ lists: SharepointList[] }>('/api/tools/sharepoint/lists', {
searchParams: {
credentialId: context.credentialId,
credentialId,
siteId: context.siteId,
},
})
+6
View File
@@ -18,6 +18,9 @@ export interface SelectorResolutionArgs {
siteId?: string
collectionId?: string
spreadsheetId?: string
baseId?: string
datasetId?: string
serviceDeskId?: string
}
export function resolveSelectorForSubBlock(
@@ -38,6 +41,9 @@ export function resolveSelectorForSubBlock(
siteId: args.siteId,
collectionId: args.collectionId,
spreadsheetId: args.spreadsheetId,
baseId: args.baseId,
datasetId: args.datasetId,
serviceDeskId: args.serviceDeskId,
mimeType: subBlock.mimeType,
},
allowSearch: subBlock.selectorAllowSearch ?? true,
@@ -18,6 +18,9 @@ interface SelectorDisplayNameArgs {
planId?: string
teamId?: string
knowledgeBaseId?: string
baseId?: string
datasetId?: string
serviceDeskId?: string
}
export function useSelectorDisplayName({
@@ -30,6 +33,9 @@ export function useSelectorDisplayName({
planId,
teamId,
knowledgeBaseId,
baseId,
datasetId,
serviceDeskId,
}: SelectorDisplayNameArgs) {
const detailId = typeof value === 'string' && value.length > 0 ? value : undefined
@@ -43,6 +49,9 @@ export function useSelectorDisplayName({
planId,
teamId,
knowledgeBaseId,
baseId,
datasetId,
serviceDeskId,
})
}, [
subBlock,
@@ -54,6 +63,9 @@ export function useSelectorDisplayName({
planId,
teamId,
knowledgeBaseId,
baseId,
datasetId,
serviceDeskId,
])
const key = resolution?.key
@@ -52,6 +52,9 @@ interface ExtendedSelectorContext {
siteId?: string
collectionId?: string
spreadsheetId?: string
baseId?: string
datasetId?: string
serviceDeskId?: string
}
function getSemanticFallback(subBlockId: string, subBlockConfig?: SubBlockConfig): string {
@@ -163,6 +166,9 @@ async function resolveSelectorValue(
siteId: extendedContext.siteId,
collectionId: extendedContext.collectionId,
spreadsheetId: extendedContext.spreadsheetId,
baseId: extendedContext.baseId,
datasetId: extendedContext.datasetId,
serviceDeskId: extendedContext.serviceDeskId,
}
if (definition.fetchById) {
@@ -240,6 +246,9 @@ function extractExtendedContext(
siteId: getStringValue('siteId'),
collectionId: getStringValue('collectionId'),
spreadsheetId: getStringValue('spreadsheetId') || getStringValue('fileId'),
baseId: getStringValue('baseId') || getStringValue('baseSelector'),
datasetId: getStringValue('datasetId') || getStringValue('datasetSelector'),
serviceDeskId: getStringValue('serviceDeskId') || getStringValue('serviceDeskSelector'),
}
}
@@ -313,6 +322,9 @@ export async function resolveValueForDisplay(
siteId: extendedContext.siteId,
collectionId: extendedContext.collectionId,
spreadsheetId: extendedContext.spreadsheetId,
baseId: extendedContext.baseId,
datasetId: extendedContext.datasetId,
serviceDeskId: extendedContext.serviceDeskId,
})
if (resolution?.key) {