From 89fc14bb4352a26e450ccf78dee61b4f46baee12 Mon Sep 17 00:00:00 2001 From: Caleb Roseland Date: Fri, 24 Nov 2023 13:15:26 -0600 Subject: [PATCH] fix plugin path matching, add coverage --- app/utils/deep_link/index.ts | 12 +++++-- app/utils/url/path.ts | 2 +- app/utils/url/test.ts | 61 ++++++++++++++++++++++++++++++++++++ types/launch/index.ts | 1 + 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/app/utils/deep_link/index.ts b/app/utils/deep_link/index.ts index b2aa88a3c..04dc46095 100644 --- a/app/utils/deep_link/index.ts +++ b/app/utils/deep_link/index.ts @@ -169,10 +169,16 @@ export function parseDeepLink(deepLinkUrl: string): DeepLinkWithData { return {type: DeepLink.Permalink, url: deepLinkUrl, data: {serverUrl, teamName, postId}}; } - const pluginMatch = match<{serverUrl: string; id: string}>(`:serverUrl(.*)/plugins/:id(${PLUGIN_ID_PATH_PATTERN})`)(url); + const pluginMatch = match<{serverUrl: string; id: string; route?: string[]}>(`:serverUrl(.*)/plugins/:id(${PLUGIN_ID_PATH_PATTERN})/:route+`)(url); if (pluginMatch) { - const {params: {serverUrl, id}} = pluginMatch; - return {type: DeepLink.Plugin, url: deepLinkUrl, data: {serverUrl, teamName: '', id}}; + const {params: {serverUrl, id, route}} = pluginMatch; + const data: DeepLinkWithData['data'] = {serverUrl, teamName: '', id}; + + if (route) { + data.route = route.join('/'); + } + + return {type: DeepLink.Plugin, url: deepLinkUrl, data}; } } catch (err) { // do nothing just return invalid deeplink diff --git a/app/utils/url/path.ts b/app/utils/url/path.ts index bf3afe95c..19a579512 100644 --- a/app/utils/url/path.ts +++ b/app/utils/url/path.ts @@ -2,7 +2,7 @@ // See LICENSE.txt for license information. export const ID_PATH_PATTERN = '[a-z0-9]{26}'; -export const PLUGIN_ID_PATH_PATTERN = '^[a-zA-Z0-9-_.]+$'; +export const PLUGIN_ID_PATH_PATTERN = '[a-zA-Z0-9-_.]{3,190}'; // This should cover: // - Team name (lowercase english characters, numbers or -) diff --git a/app/utils/url/test.ts b/app/utils/url/test.ts index eed9fab90..774c399a0 100644 --- a/app/utils/url/test.ts +++ b/app/utils/url/test.ts @@ -403,6 +403,67 @@ describe('UrlUtils', () => { }, expected: null, }, + { + name: 'should match plugin path on a Server hosted in a Subpath', + input: { + url: DEEPLINK_URL_ROOT + '/subpath/deepsubpath/plugins/com.acme.abc-test/api/testroute', + serverURL: SERVER_WITH_SUBPATH, + siteURL: SERVER_WITH_SUBPATH, + }, + expected: { + data: { + id: 'com.acme.abc-test', + route: 'api/testroute', + serverUrl: URL_PATH_NO_PROTOCOL, + teamName: '', + }, + type: DeepLinkType.Plugin, + }, + }, + { + name: 'should match plugin path with single-level route', + input: { + url: DEEPLINK_URL_ROOT + '/subpath/deepsubpath/plugins/abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_ab/testroute', + serverURL: SERVER_WITH_SUBPATH, + siteURL: SERVER_WITH_SUBPATH, + }, + expected: { + data: { + id: 'abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_ab', + route: 'testroute', + serverUrl: URL_PATH_NO_PROTOCOL, + teamName: '', + }, + type: DeepLinkType.Plugin, + }, + }, + { + name: 'should not match plugin path with invalid plugin id len=2', + input: { + url: DEEPLINK_URL_ROOT + '/subpath/deepsubpath/plugins/ab/api/testroute', + serverURL: SERVER_WITH_SUBPATH, + siteURL: SERVER_WITH_SUBPATH, + }, + expected: null, + }, + { + name: 'should not match plugin path with invalid plugin id len=191', + input: { + url: DEEPLINK_URL_ROOT + '/subpath/deepsubpath/plugins/abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc_abc/api/testroute', + serverURL: SERVER_WITH_SUBPATH, + siteURL: SERVER_WITH_SUBPATH, + }, + expected: null, + }, + { + name: 'should not match plugin path without a route', + input: { + url: DEEPLINK_URL_ROOT + '/subpath/deepsubpath/plugins/abc', + serverURL: SERVER_WITH_SUBPATH, + siteURL: SERVER_WITH_SUBPATH, + }, + expected: null, + }, ]; for (const test of tests) { diff --git a/types/launch/index.ts b/types/launch/index.ts index e25baf93a..4dffb4d71 100644 --- a/types/launch/index.ts +++ b/types/launch/index.ts @@ -26,6 +26,7 @@ export interface DeepLinkGM extends DeepLink { export interface DeepLinkPlugin extends DeepLink { id: string; + route?: string; } export type DeepLinkType = typeof DeepLink[keyof typeof DeepLink];