diff --git a/package-lock.json b/package-lock.json index e4496b88f..2ef8f4e02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "graph-explorer-v2", - "version": "9.7.0", + "version": "9.8.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "graph-explorer-v2", - "version": "9.7.0", + "version": "9.8.0", "dependencies": { "@augloop/types-core": "file:packages/types-core-2.16.189.tgz", "@axe-core/webdriverjs": "4.8.4", @@ -9801,9 +9801,9 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, "node_modules/follow-redirects": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", - "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", diff --git a/package.json b/package.json index 8d3d7eafc..0b2a64d67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "graph-explorer-v2", - "version": "9.7.0", + "version": "9.8.0", "private": true, "dependencies": { "@augloop/types-core": "file:packages/types-core-2.16.189.tgz", diff --git a/src/app/utils/query-parameter-sanitization.ts b/src/app/utils/query-parameter-sanitization.ts index e9ff67407..514b124e8 100644 --- a/src/app/utils/query-parameter-sanitization.ts +++ b/src/app/utils/query-parameter-sanitization.ts @@ -16,6 +16,7 @@ const LAMBDA_OPERATORS = ['/any', '/all']; // REGEXES const ALL_ALPHA_REGEX = /^[a-z]+$/i; +const ONE_NUMERIC_REGEX = /^(?=[a-zA-Z]*\d[a-zA-Z]*$)[a-zA-Z\d]*$/; const POSITIVE_INTEGER_REGEX = /^[1-9]\d*$/; // Matches media type formats // Examples: https://www.iana.org/assignments/media-types/media-types.xhtml @@ -62,6 +63,10 @@ function isAllAlpha(str: string): boolean { return ALL_ALPHA_REGEX.test(str); } +function isAlphaNumeric(str: string): boolean { + return ONE_NUMERIC_REGEX.test(str); +} + function isPlaceHolderSegment(segment: string) { return segment.startsWith('{') && segment.endsWith('}') } @@ -483,6 +488,7 @@ function sanitizeFilterQueryOptionValue(queryParameterValue: string): string { export { isPropertyName, isAllAlpha, + isAlphaNumeric, isPlaceHolderSegment, sanitizeQueryParameter } diff --git a/src/app/utils/query-url-sanitization.ts b/src/app/utils/query-url-sanitization.ts index c07246162..8e07d5b72 100644 --- a/src/app/utils/query-url-sanitization.ts +++ b/src/app/utils/query-url-sanitization.ts @@ -2,6 +2,7 @@ import { IQuery } from '../../types/query-runner'; import { isAllAlpha, + isAlphaNumeric, isPlaceHolderSegment, sanitizeQueryParameter } from './query-parameter-sanitization'; @@ -101,13 +102,13 @@ function sanitizedQueryUrl(url: string): string { * @param segment */ function sanitizePathSegment(previousSegment: string, segment: string): string { - const segmentsToIgnore = ['$value', '$count', '$ref', '$batch']; if ( isAllAlpha(segment) || + isAlphaNumeric(segment) || isDeprecation(segment) || SANITIZED_ITEM_PATH_REGEX.test(segment) || - segmentsToIgnore.includes(segment.toLowerCase()) || + segment.startsWith('$') || ENTITY_NAME_REGEX.test(segment) ) { return segment; diff --git a/src/app/utils/resources/resources-filter.ts b/src/app/utils/resources/resources-filter.ts index 03e182c2a..a30f0f18e 100644 --- a/src/app/utils/resources/resources-filter.ts +++ b/src/app/utils/resources/resources-filter.ts @@ -24,7 +24,7 @@ function getMatchingResourceForUrl(url: string, resources: IResource[]): IResour let matching = [...resources]; let node; for (const path of parts) { - if (hasPlaceHolders(path)) { + if (hasPlaceHolders(path) && path !== '{undefined-id}') { node = matching.find(k => hasPlaceHolders(k.segment)); matching = node?.children || []; } else { diff --git a/src/app/views/query-runner/query-input/auto-complete/AutoComplete.tsx b/src/app/views/query-runner/query-input/auto-complete/AutoComplete.tsx index 7dec3b35d..23db381a5 100644 --- a/src/app/views/query-runner/query-input/auto-complete/AutoComplete.tsx +++ b/src/app/views/query-runner/query-input/auto-complete/AutoComplete.tsx @@ -241,9 +241,9 @@ const AutoComplete = (props: IAutoCompleteProps) => { const appendSuggestionToUrl = (selected: string) => { if (!selected) { return; } - + const { context } = getLastDelimiterInUrl(queryUrl); let query = selected; - if (selected.startsWith(delimiters.DOLLAR.symbol)) { + if (selected.startsWith(delimiters.DOLLAR.symbol) && context === 'parameters') { selected += delimiters.EQUALS.symbol; query = ''; } diff --git a/src/app/views/query-runner/query-input/auto-complete/suffix/documentation.ts b/src/app/views/query-runner/query-input/auto-complete/suffix/documentation.ts index 605d8d97f..162381e76 100644 --- a/src/app/views/query-runner/query-input/auto-complete/suffix/documentation.ts +++ b/src/app/views/query-runner/query-input/auto-complete/suffix/documentation.ts @@ -69,7 +69,7 @@ class DocumentationService implements IDocumentationService { if (matchingResource && matchingResource.labels.length > 0) { const currentLabel = matchingResource.labels.filter(k => k.name === this.queryVersion)[0]; - const method = currentLabel.methods[0]; + const method = currentLabel?.methods[0]; if (typeof method === 'string') { return null; } diff --git a/src/modules/suggestions/suggestions.ts b/src/modules/suggestions/suggestions.ts index a31d8aef9..33abb2132 100644 --- a/src/modules/suggestions/suggestions.ts +++ b/src/modules/suggestions/suggestions.ts @@ -52,20 +52,12 @@ class Suggestions implements ISuggestions { } private createOpenApiResponse(versionedResources: IResource[], url: string): IParsedOpenApiResponse { - const paths: string[] = []; - - versionedResources.forEach((resource: IResource) => { - if (!resource.segment.contains('$')) { - paths.push(resource.segment); - } - }); - const response: IParsedOpenApiResponse = { createdAt: '', parameters: [{ verb: 'get', values: [], - links: paths + links: versionedResources.map((resource: IResource) => resource.segment) }], url };