Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 5 additions & 11 deletions .github/actions/webapp-setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,20 @@ runs:
webapp/channels/node_modules
webapp/platform/client/node_modules
webapp/platform/components/node_modules
webapp/platform/shared/node_modules
webapp/platform/types/node_modules
key: node-modules-${{ runner.os }}-${{ hashFiles('webapp/package-lock.json') }}
- name: ci/cache-platform-builds
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
id: cache-platform-builds
with:
path: |
webapp/platform/types/lib
webapp/platform/client/lib
webapp/platform/components/dist
key: platform-builds-${{ runner.os }}-${{ hashFiles('webapp/platform/types/src/**', 'webapp/platform/client/src/**', 'webapp/platform/components/src/**') }}
- name: ci/get-node-modules
if: steps.cache-node-modules.outputs.cache-hit != 'true'
shell: bash
working-directory: webapp
run: |
make node_modules
- name: ci/build-platform-packages
if: steps.cache-platform-builds.outputs.cache-hit != 'true'
# These are built automatically when depenedencies are installed, but they aren't cached properly, so we need to
# manually build them when the cache is hit. They aren't worth caching because they have too many dependencies.
if: steps.cache-node-modules.outputs.cache-hit == 'true'
shell: bash
working-directory: webapp
run: |
npm run build --workspace=platform/types --workspace=platform/client --workspace=platform/components
npm run postinstall
3 changes: 2 additions & 1 deletion .github/workflows/webapp-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,15 @@ jobs:
env:
NODE_OPTIONS: --max_old_space_size=5120
run: |
npm run test-ci --workspace=platform/client --workspace=platform/components -- --coverage
npm run test-ci --workspace=platform/client --workspace=platform/components --workspace=platform/shared -- --coverage
- name: ci/upload-coverage-artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: coverage-platform
path: |
./webapp/platform/client/coverage
./webapp/platform/components/coverage
./webapp/platform/shared/coverage
retention-days: 1

test-mattermost-redux:
Expand Down
2 changes: 1 addition & 1 deletion server/.go-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.24.11
1.24.13
2 changes: 1 addition & 1 deletion server/build/Dockerfile.buildenv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mattermost/golang-bullseye:1.24.11@sha256:648e6d4bd76751787cf8eb2674942f931a01043872ce15ac9501382dabcefbe8
FROM mattermost/golang-bullseye:1.24.13@sha256:d9d9a35369413840836f677db08beb0aec784a966fe2a1ba1e60dc9baa64e881
ARG NODE_VERSION=20.11.1

RUN apt-get update && apt-get install -y make git apt-transport-https ca-certificates curl software-properties-common build-essential zip xmlsec1 jq pgloader gnupg
Expand Down
2 changes: 1 addition & 1 deletion server/build/Dockerfile.buildenv-fips
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM cgr.dev/mattermost.com/go-msft-fips:1.24.11-dev@sha256:181a7db41bbff8cf0e522bd5f951a44f2a39a5f58ca930930dfbecdc6b690272
FROM cgr.dev/mattermost.com/go-msft-fips:1.24.13-dev@sha256:46c7f9e469ab1c83a7c1f3d1dfdf9f0aee7ef8a1c93d39a2270af3560b4008b4
ARG NODE_VERSION=20.11.1

RUN apk add curl ca-certificates mailcap unrtf wv poppler-utils tzdata gpg xmlsec
Expand Down
4 changes: 4 additions & 0 deletions server/channels/api4/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ func (api *API) APILocal(h handlerFunc, opts ...APIHandlerOption) http.Handler {
}

func (api *API) RateLimitedHandler(apiHandler http.Handler, settings model.RateLimitSettings) http.Handler {
if !*api.srv.Config().RateLimitSettings.Enable {
return apiHandler
}

settings.SetDefaults()

rateLimiter, err := app.NewRateLimiter(&settings, []string{})
Expand Down
2 changes: 1 addition & 1 deletion server/channels/api4/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func (api *API) InitUser() {
api.BaseRoutes.User.Handle("/mfa", api.APISessionRequiredMfa(updateUserMfa)).Methods(http.MethodPut)
api.BaseRoutes.User.Handle("/mfa/generate", api.APISessionRequiredMfa(generateMfaSecret)).Methods(http.MethodPost)

api.BaseRoutes.Users.Handle("/login", api.APIHandler(login)).Methods(http.MethodPost)
api.BaseRoutes.Users.Handle("/login", api.RateLimitedHandler(api.APIHandler(login), model.RateLimitSettings{PerSec: model.NewPointer(5), MaxBurst: model.NewPointer(10)})).Methods(http.MethodPost)
api.BaseRoutes.Users.Handle("/login/sso/code-exchange", api.APIHandler(loginSSOCodeExchange)).Methods(http.MethodPost)
api.BaseRoutes.Users.Handle("/login/desktop_token", api.RateLimitedHandler(api.APIHandler(loginWithDesktopToken), model.RateLimitSettings{PerSec: model.NewPointer(2), MaxBurst: model.NewPointer(1)})).Methods(http.MethodPost)
api.BaseRoutes.Users.Handle("/login/switch", api.APIHandler(switchAccountType)).Methods(http.MethodPost)
Expand Down
2 changes: 1 addition & 1 deletion server/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/mattermost/mattermost/server/v8

go 1.24.11
go 1.24.13

require (
code.sajari.com/docconv/v2 v2.0.0-pre.4
Expand Down
2 changes: 1 addition & 1 deletion server/public/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/mattermost/mattermost/server/public

go 1.24.11
go 1.24.13

require (
github.com/blang/semver/v4 v4.0.0
Expand Down
1 change: 1 addition & 0 deletions webapp/.gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.eslintcache
junit.xml
node_modules
.parcel-cache
*.tsbuildinfo
.rollup.cache
*.tar.gz
Expand Down
3 changes: 1 addition & 2 deletions webapp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ endif
clean: ## Clears cached; deletes node_modules and dist directories
@echo Cleaning Web App

npm run clean --workspaces --if-present
rm -rf node_modules
npm run clean

.PHONY: package
package: node_modules dist ## Generates ./mattermost-webapp.tar.gz for use by someone customizing the web app
Expand Down
1 change: 1 addition & 0 deletions webapp/channels/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"@guyplusplus/turndown-plugin-gfm": "1.0.7",
"@mattermost/client": "11.4.0",
"@mattermost/desktop-api": "6.0.0-1",
"@mattermost/shared": "11.4.0",
"@mattermost/types": "11.4.0",
"@mui/base": "5.0.0-alpha.127",
"@mui/material": "5.11.16",
Expand Down
61 changes: 2 additions & 59 deletions webapp/channels/src/components/emoji/render_emoji.tsx
Original file line number Diff line number Diff line change
@@ -1,63 +1,6 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import React from 'react';
import type {MouseEvent, KeyboardEvent} from 'react';
import {useSelector} from 'react-redux';
import {Emoji} from '@mattermost/shared/components/emoji';

import {getEmojiImageUrl} from 'mattermost-redux/utils/emoji_utils';

import {getEmojiMap} from 'selectors/emojis';

import type {GlobalState} from 'types/store';

const emptyEmojiStyle = {};

interface ComponentProps {
emojiName: string;
size?: number;
emojiStyle?: React.CSSProperties;
onClick?: (event: MouseEvent<HTMLSpanElement> | KeyboardEvent<HTMLSpanElement>) => void;
}

const RenderEmoji = ({
emojiName = '',
emojiStyle = emptyEmojiStyle,
size = 16,
onClick,
}: ComponentProps) => {
const emojiMap = useSelector((state: GlobalState) => getEmojiMap(state));

if (!emojiName) {
return null;
}

const emojiFromMap = emojiMap.get(emojiName);
if (!emojiFromMap) {
return null;
}
const emojiImageUrl = getEmojiImageUrl(emojiFromMap);

return (
<span
onClick={onClick}
className='emoticon'
aria-label={`:${emojiName}:`}
data-emoticon={emojiName}
style={{
backgroundImage: `url(${emojiImageUrl})`,
backgroundSize: 'contain',
height: size,
width: size,
maxHeight: size,
maxWidth: size,
minHeight: size,
minWidth: size,
overflow: 'hidden',
...emojiStyle,
}}
/>
);
};

export default React.memo(RenderEmoji);
export default Emoji;
18 changes: 11 additions & 7 deletions webapp/channels/src/components/root/root_provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,22 @@ import ThemeProvider from 'components/theme_provider';
import WebSocketClient from 'client/web_websocket_client';
import {WebSocketContext} from 'utils/use_websocket';

import SharedPackageProvider from './shared_package_provider';

type Props = {
children: React.ReactNode;
}

export default function RootProvider(props: Props) {
return (
<IntlProvider>
<WebSocketContext.Provider value={WebSocketClient}>
<ThemeProvider>
{props.children}
</ThemeProvider>
</WebSocketContext.Provider>
</IntlProvider>
<SharedPackageProvider>
<IntlProvider>
<WebSocketContext.Provider value={WebSocketClient}>
<ThemeProvider>
{props.children}
</ThemeProvider>
</WebSocketContext.Provider>
</IntlProvider>
</SharedPackageProvider>
);
}
48 changes: 48 additions & 0 deletions webapp/channels/src/components/root/shared_package_provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import React from 'react';
import {useSelector} from 'react-redux';

import {SharedProvider} from '@mattermost/shared/context';
import type {Emoji} from '@mattermost/types/emojis';

import {getEmojiImageUrl} from 'mattermost-redux/utils/emoji_utils';

import {getEmojiMap} from 'selectors/emojis';

import type {GlobalState} from 'types/store';

export interface SharedPackageProviderProps {
children: React.ReactNode;
}

export default function SharedPackageProvider({children}: SharedPackageProviderProps) {
return (
<SharedProvider
useEmojiByName={useEmojiByName}
useEmojiUrl={useEmojiUrl}
>
{children}
</SharedProvider>
);
}

function useEmojiByName(name: string) {
// This isn't defined for use elsewhere because makeUseEntity currently needs additional logic for handling emojis
const emojiMap = useSelector((state: GlobalState) => getEmojiMap(state));

if (!name) {
return undefined;
}

return emojiMap.get(name);
}

function useEmojiUrl(emoji?: Emoji) {
if (!emoji) {
return '';
}

return getEmojiImageUrl(emoji);
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ describe('EmojiUtils', () => {
category: 'activities',
short_names: ['sampleEmoji'],
short_name: 'sampleEmoji',
batch: 2,
image: 'sampleEmoji.png',
});
expect(EmojiUtils.isSystemEmoji(sampleEmoji)).toBe(true);
});
Expand All @@ -64,8 +62,6 @@ describe('EmojiUtils', () => {
name: 'sampleEmoji',
short_names: ['sampleEmoji'],
short_name: 'sampleEmoji',
batch: 2,
image: 'sampleEmoji.png',
});
expect(EmojiUtils.isSystemEmoji(sampleEmoji)).toBe(true);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import type {Emoji, SystemEmoji} from '@mattermost/types/emojis';
import {isSystemEmoji, type Emoji} from '@mattermost/types/emojis';

import {Client4} from 'mattermost-redux/client';

export function isSystemEmoji(emoji: Emoji): emoji is SystemEmoji {
if ('category' in emoji) {
return emoji.category !== 'custom';
}

return !('id' in emoji);
}
export {isSystemEmoji};

export function getEmojiImageUrl(emoji: Emoji): string {
// If its the mattermost custom emoji
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -701,10 +701,8 @@ class TestHelper {
return {
name: '',
category: 'recent',
image: '',
short_name: '',
short_names: [],
batch: 0,
unified: '',
...override,
};
Expand Down
20 changes: 12 additions & 8 deletions webapp/channels/src/tests/react_testing_utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import type {DeepPartial} from '@mattermost/types/utilities';
import configureStore from 'store';
import globalStore from 'stores/redux_store';

import SharedPackageProvider from 'components/root/shared_package_provider';

import WebSocketClient from 'client/web_websocket_client';
import mergeObjects from 'packages/mattermost-redux/test/merge_objects';
import mockStore from 'tests/test_store';
Expand Down Expand Up @@ -183,14 +185,16 @@ const Providers = ({children, store, history, options}: RenderStateProps) => {
return (
<Provider store={store}>
<Router history={history}>
<IntlProvider
locale={options.locale}
messages={options.intlMessages}
>
<WebSocketContext.Provider value={WebSocketClient}>
{children}
</WebSocketContext.Provider>
</IntlProvider>
<SharedPackageProvider>
<IntlProvider
locale={options.locale}
messages={options.intlMessages}
>
<WebSocketContext.Provider value={WebSocketClient}>
{children}
</WebSocketContext.Provider>
</IntlProvider>
</SharedPackageProvider>
</Router>
</Provider>
);
Expand Down
2 changes: 0 additions & 2 deletions webapp/channels/src/utils/test_helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -452,10 +452,8 @@ export class TestHelper {
return {
name: '',
category: 'recent',
image: '',
short_name: '',
short_names: [],
batch: 0,
unified: '',
...override,
};
Expand Down
5 changes: 5 additions & 0 deletions webapp/channels/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,11 @@ var config = {
],
}),
],
watchOptions: {

// By default, Webpack doesn't watch node_modules for changes, but we want it to watch packages in the monorepo
ignored: /node_modules([\\]+|\/)(?!@mattermost\/(client|components|types|shared))/,
},
};

function generateCSP() {
Expand Down
Loading
Loading