[MM-53904] Fix MM-53904 (#24622)

* Fix MM-53904

* Simplify regex

* Simplify utils regex

* Fix lint

* Address feedback and polish regex

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
Daniel Espino García 2023-10-19 12:59:02 +02:00 committed by GitHub
parent 6f4d362f9f
commit f62634622f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 36 additions and 13 deletions

View File

@ -11,6 +11,8 @@ import PlaybookRunner from 'components/channel_layout/playbook_runner';
import LoadingScreen from 'components/loading_screen';
import PermalinkView from 'components/permalink_view';
import {IDENTIFIER_PATH_PATTERN, ID_PATH_PATTERN, TEAM_NAME_PATH_PATTERN} from 'utils/path';
import type {OwnProps, PropsFromRedux} from './index';
const LazyChannelHeaderMobile = makeAsyncComponent(
@ -92,7 +94,7 @@ export default class CenterChannel extends React.PureComponent<Props, State> {
<div className='row main'>
<Switch>
<Route
path={`${url}/pl/:postid`}
path={`${url}/pl/:postid(${ID_PATH_PATTERN})`}
render={(props) => (
<PermalinkView
{...props}
@ -101,22 +103,22 @@ export default class CenterChannel extends React.PureComponent<Props, State> {
)}
/>
<Route
path='/:team/:path(channels|messages)/:identifier/:postid?'
path={`/:team(${TEAM_NAME_PATH_PATTERN})/:path(channels|messages)/:identifier(${IDENTIFIER_PATH_PATTERN})/:postid(${ID_PATH_PATTERN})?`}
component={ChannelIdentifierRouter}
/>
<Route
path='/:team/_playbooks/:playbookId/run'
path={`/:team(${TEAM_NAME_PATH_PATTERN})/_playbooks/:playbookId(${ID_PATH_PATTERN})/run`}
>
<PlaybookRunner/>
</Route>
{isCollapsedThreadsEnabled ? (
<Route
path='/:team/threads/:threadIdentifier?'
path={`/:team(${TEAM_NAME_PATH_PATTERN})/threads/:threadIdentifier(${ID_PATH_PATTERN})?`}
component={LazyGlobalThreads}
/>
) : null}
<Route
path='/:team/drafts'
path={`/:team(${TEAM_NAME_PATH_PATTERN})/drafts`}
component={LazyDrafts}
/>

View File

@ -117,7 +117,7 @@ exports[`components/Root Routes Should mount public product routes 1`] = `
/>
<LoggedInRoute
component={[Function]}
path="/:team"
path="/:team([a-z0-9\\\\-_]+)"
theme={Object {}}
/>
<Connect(RootRedirect) />

View File

@ -55,6 +55,7 @@ import Pluggable from 'plugins/pluggable';
import A11yController from 'utils/a11y_controller';
import {PageLoadContext, StoragePrefixes} from 'utils/constants';
import {EmojiIndicesByAlias} from 'utils/emoji';
import {TEAM_NAME_PATH_PATTERN} from 'utils/path';
import {getSiteURL} from 'utils/url';
import * as UserAgent from 'utils/user_agent';
import * as Utils from 'utils/utils';
@ -111,7 +112,7 @@ const OnBoardingTaskList = makeAsyncComponent('OnboardingTaskList', LazyOnBoardi
type LoggedInRouteProps<T> = {
component: React.ComponentType<T>;
path: string;
path: string | string[];
theme?: Theme; // the routes that send the theme are the ones that will actually need to show the onboarding tasklist
};
function LoggedInRoute<T>(props: LoggedInRouteProps<T>) {
@ -644,7 +645,7 @@ export default class Root extends React.PureComponent<Props, State> {
))}
<LoggedInRoute
theme={this.props.theme}
path={'/:team'}
path={`/:team(${TEAM_NAME_PATH_PATTERN})`}
component={TeamController}
/>
<RootRedirect/>

View File

@ -19,6 +19,7 @@ import useTelemetryIdentitySync from 'components/common/hooks/useTelemetryIdenti
import Constants from 'utils/constants';
import {cmdOrCtrlPressed, isKeyPressed} from 'utils/keyboard';
import {TEAM_NAME_PATH_PATTERN} from 'utils/path';
import {isIosSafari} from 'utils/user_agent';
import type {OwnProps, PropsFromRedux} from './index';
@ -208,17 +209,17 @@ function TeamController(props: Props) {
return (
<Switch>
<Route
path={'/:team/integrations'}
path={`/:team(${TEAM_NAME_PATH_PATTERN})/integrations`}
component={BackstageController}
/>
<Route
path={'/:team/emoji'}
path={`/:team(${TEAM_NAME_PATH_PATTERN})/emoji`}
component={BackstageController}
/>
{props.plugins?.map((plugin) => (
<Route
key={plugin.id}
path={'/:team/' + (plugin as any).route}
path={`/:team(${TEAM_NAME_PATH_PATTERN})/` + (plugin as any).route}
render={() => (
<Pluggable
pluggableName={'NeedsTeamComponent'}

View File

@ -0,0 +1,19 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
export const ID_PATH_PATTERN = '[a-z0-9]{26}';
// This should cover:
// - Team name (lowercase english characters, numbers or -)
// - Two ids separated by __ (userID__userID)
export const TEAM_NAME_PATH_PATTERN = '[a-z0-9\\-_]+';
// This should cover:
// - Channel name
// - Channel ID
// - Group Channel Name (40 length UID)
// - DM Name (userID__userID)
// - Username prefixed by a @
// - User ID
// - Email
export const IDENTIFIER_PATH_PATTERN = '[@a-zA-Z\\-_0-9][@a-zA-Z\\-_0-9.]*';

View File

@ -1333,7 +1333,7 @@ export function isValidPassword(password: string, passwordConfig: ReturnType<typ
}
function isChannelOrPermalink(link: string) {
let match = (/\/([^/]+)\/channels\/(\S+)/).exec(link);
let match = (/\/([a-z0-9\-_]+)\/channels\/([a-z0-9\-__][a-z0-9\-__.]+)/).exec(link);
if (match) {
return {
type: 'channel',
@ -1341,7 +1341,7 @@ function isChannelOrPermalink(link: string) {
channelName: match[2],
};
}
match = (/\/([^/]+)\/pl\/(\w+)/).exec(link);
match = (/\/([a-z0-9\-__]+)\/pl\/([a-z0-9]+)/).exec(link);
if (match) {
return {
type: 'permalink',