* MM-67274: Fix panic in getBrowserVersion with empty User-Agent version
Refactor getBrowserVersion to use a table-driven approach that
centralizes bounds checking, preventing panic when User-Agent strings
contain identifiers like "Mattermost Mobile/" with no version token.
* Refactor user agent tests to use structured test cases
Move expected values into the testUserAgent struct for clarity,
making it easier to see what each test case expects at a glance.
* Add Client4 route building functions
* Make DoAPIRequestWithHeaders add the API URL
This makes it consistent with the other DoAPIXYZ functions, which all
prepend the provided URL with the client's API URL.
* Use the new route building logic in Client4
* Address review comments
- clean renamed to cleanSegment
- JoinRoutes and JoinSegments joined in Join
- newClientRoute uses Join
* Fix new routes from merge
* Remove unused import
* Simplify error handling around clientRoute (#34870)
---------
Co-authored-by: Jesse Hallam <jesse@mattermost.com>
Co-authored-by: Jesse Hallam <jesse.hallam@gmail.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
Canonicalize IPv4-mapped IPv6 addresses (e.g., ::ffff:127.0.0.1) to
their native IPv4 form in IsReservedIP before checking against reserved
IP ranges. This prevents attackers from bypassing SSRF protections by
using IPv4-mapped IPv6 literals to access internal services.
* remove permalink embeds when user loses access to orginating channel
* remove posts & embeds on team_leave event; simplify preview index.ts
* cleanup
* remove dead code
* more dead code elimination
* MM-67269 - Fix popout windows for subpath deployments
Popout windows were failing with 404 errors when Mattermost is served
from a subpath (e.g., https://company.com/mattermost). The popout
functions were constructing URLs without including the subpath prefix.
Changes:
- Updated popoutThread() and popoutRhsPlugin() to use getBasePath()
helper function which includes window.basename
- Added unit tests to verify popout URLs include subpath when configured
- Follows established pattern used throughout codebase (getSiteURL,
cookie paths, React Router)
This ensures popout windows open at the correct URL:
/subpath/_popout/... instead of /_popout/...
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
* Clear mocks and set default base path in tests
---------
Co-authored-by: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
* Add pluggable ChannelHeaderIcon
* Add orchestration for post/channel/team citations in post render
* Updates to suit new format cor citations
* Fix linter
* Fix stylelint property order errors in _markdown.scss
* Fix TypeScript type errors
- Add missing ChannelHeaderIcon to initialComponents in plugins reducer
- Fix SelectProps generic to use 'false' instead of 'boolean' for isMulti in dropdown_input_hybrid
* Update channel_header snapshots to include ChannelHeaderIcon Pluggable
* PR feedback changes
* Add snapshots
* Add export for DatePicker
* PR Feedback
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
* Add tooltip support and error handling for action buttons
- Add tooltip field to PostAction type definition
- Display tooltips on hover for action buttons
- Add comprehensive error handling for button actions
- Show error messages when actions fail
- Clear previous errors on subsequent actions
- Add tests for error handling functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add E2E tests for action button error handling and tooltips
- Test error message display when action buttons fail
- Test error clearing when successful actions are performed
- Test tooltip display on action button hover
- Use scoped selectors to avoid test interference
- Cover complete error lifecycle and tooltip functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Use WithTooltip component for action button tooltips
Replace native HTML title attribute with WithTooltip component to provide
consistent tooltip styling and behavior across the application.
Changes:
- Import and wrap ActionBtn with WithTooltip component
- Remove title attribute from ActionBtn
- Update E2E test to check for .tooltipContainer instead of title attribute
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix TypeScript errors and test patterns in message attachment tests
- Fix TypeScript type errors in mock event objects by using arrow functions instead of jest.fn()
- Update async test pattern to use process.nextTick() with done callback instead of await
- Update test snapshots to reflect error handling wrapper div
- Fix whitespace formatting in E2E test file
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
* updated actionError to accept react node, replace hardcoded error with FormattedMessage components
* Fix test to handle FormattedMessage in actionError state
Update test expectation to check for FormattedMessage React element
instead of plain string when no error message is provided. This aligns
with the recent change to support internationalization in error messages.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
* Disable tooltip interactions when no tooltip text is present
Adds disabled prop to WithTooltip component when action.tooltip is empty or undefined, preventing unnecessary tooltip event handlers from being attached to action buttons that don't have tooltips.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
* Add tests for action button tooltip behavior
Adds three test cases to verify tooltip functionality:
- Tooltip is disabled when action.tooltip is undefined
- Tooltip is disabled when action.tooltip is empty string
- Tooltip is enabled and displays correctly when action.tooltip has a value
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
* fix e2e test
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
* [MM-67290] Document that Elasticsearch backend type change requires server restart
* Update Elasticsearch settings test snapshots
Update snapshots to reflect the new help text for the backend type
setting that documents the server restart requirement.
* MM-61383 - add back offline user help for messagging
* Apply suggestions from code review
Co-authored-by: Matthew Birtch <mattbirtch@gmail.com>
* Apply suggestions from code review
Co-authored-by: Matthew Birtch <mattbirtch@gmail.com>
* Use non-breaking spaces for code indendation display
* Fix avatar status badge being cut off in Mentioning Help page
* show help in popout, if available
* fix styling
* missing i18n
* help page titles
* missing i18n
* additional i18n
* fix missing values
* Make help link always visible, fix accessibility
* Fix CSS property ordering in help button styles
---------
Co-authored-by: Jesse Hallam <jesse.hallam@gmail.com>
Co-authored-by: Matthew Birtch <mattbirtch@gmail.com>
Co-authored-by: Jesse Hallam <jesse@mattermost.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
* Add TS definitions for every WebSocket event
* Remove unused WebSocket events
* Add a few extra fields to POSTED events
* Stop reusing WS event types as Redux actions
* Remove now-unused WS event types from mattermost-redux
* Rename some types to be clearer
* Use new WebSocketEvents and WebSocketMessage type everywhere
* Reorganize and export named types for WS messages
* Use new types in websocket_actions.jsx the best we can
* Rename websocket_actions.jsx to websocket_actions.tsx
* Migrate websocket_actions.tsx to TypeScript
* Break up websocket_messages.ts and group together WebSocketMessages types
* Rename websocket_actions.tsx to websocket_actions.ts
* remove newsletter signup and replace with terms/privacy agreement
* removed subscribeToSecurityNewsletter, made checkbox required
* update signup test to remove newsletter and ensure the terms checkbox is required
* update unit test and e2e test to reflect changes
* fix e2e test
* Removed susbcribe-newsletter endpoint in server
* Update signup.test.tsx
* remove unused css
* remove unused css
* fixed broken tests
* fixed linter issues
* Remove redundant IntlProvider and comments
* Remove usage of test IDs from Signup tests
* Remove usage of fireEvent
* Remove usage of mountWithIntl from Signup tests
* update e2e tests
* fix playwright test
* Fix Lint in signup.ts
---------
Co-authored-by: maria.nunez <maria.nunez@mattermost.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
Co-authored-by: Harrison Healey <harrisonmhealey@gmail.com>
Co-authored-by: yasserfaraazkhan <attitude3cena.yf@gmail.com>
* chore: playwright upgrade
* add luxon and chalk as dependency, and relax peer dependency to @playwright/test with >=1.55.0
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
* move measureAndReport out of setTimeOut and reduce minimum time
* fix z-index issue where system console header shows on top
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
* Remove some unused props
* Removed unused state and actions involving profilesWithoutTeam
* Remove unused page prop from DataGrid
* Remove some unused props from system console components
* Remove some unused props related to self serve and trials
* Remove unused props from post related components
* Remove unused props from user settings components
* Remove some more unused props
* Remove legacy quoteColumnName() utility
Since Mattermost only supports PostgreSQL, the quoteColumnName() helper
that was designed to handle database-specific column quoting is no longer
needed. The function was a no-op that simply returned the column name
unchanged.
Remove the function from utils.go and update status_store.go to use
the "Manual" column name directly.
* Remove legacy driver checks from store.go
Since Mattermost only supports PostgreSQL, remove conditional checks
for different database drivers:
- Simplify specialSearchChars() to always return PostgreSQL-compatible chars
- Remove driver check from computeBinaryParam()
- Remove driver check from computeDefaultTextSearchConfig()
- Simplify GetDbVersion() to use PostgreSQL syntax directly
- Remove switch statement from ensureMinimumDBVersion()
- Remove unused driver parameter from versionString()
* Remove MySQL alternatives for batch delete operations
Since Mattermost only supports PostgreSQL, remove the MySQL-specific
DELETE...LIMIT syntax and keep only the PostgreSQL array-based approach:
- reaction_store.go: Use PostgreSQL array syntax for PermanentDeleteBatch
- file_info_store.go: Use PostgreSQL array syntax for PermanentDeleteBatch
- preference_store.go: Use PostgreSQL tuple IN subquery for DeleteInvalidVisibleDmsGms
* Remove MySQL alternatives for UPDATE...FROM syntax
Since Mattermost only supports PostgreSQL, remove the MySQL-specific
UPDATE syntax that joins tables differently:
- thread_store.go: Use PostgreSQL UPDATE...FROM syntax in
MarkAllAsReadByChannels and MarkAllAsReadByTeam
- post_store.go: Use PostgreSQL UPDATE...FROM syntax in deleteThreadFiles
* Remove MySQL alternatives for JSON and subquery operations
Since Mattermost only supports PostgreSQL, remove the MySQL-specific
JSON and subquery syntax:
- thread_store.go: Use PostgreSQL JSONB operators for updating participants
- access_control_policy_store.go: Use PostgreSQL JSONB @> operator for
querying JSON imports
- session_store.go: Use PostgreSQL subquery syntax for Cleanup
- job_store.go: Use PostgreSQL subquery syntax for Cleanup
* Remove MySQL alternatives for CTE queries
Since Mattermost only supports PostgreSQL, simplify code that
uses CTEs (Common Table Expressions):
- channel_store.go: Remove MySQL CASE-based fallback in
UpdateLastViewedAt and use PostgreSQL CTE exclusively
- draft_store.go: Remove driver checks in DeleteEmptyDraftsByCreateAtAndUserId,
DeleteOrphanDraftsByCreateAtAndUserId, and determineMaxDraftSize
* Remove driver checks in migrate.go and schema_dump.go
Simplify migration code to use PostgreSQL driver directly since
PostgreSQL is the only supported database.
* Remove driver checks in sqlx_wrapper.go
Always apply lowercase named parameter transformation since PostgreSQL
is the only supported database.
* Remove driver checks in user_store.go
Simplify user store functions to use PostgreSQL-only code paths:
- Remove isPostgreSQL parameter from helper functions
- Use LEFT JOIN pattern instead of subqueries for bot filtering
- Always use case-insensitive LIKE with lower() for search
- Remove MySQL-specific role filtering alternatives
* Remove driver checks in post_store.go
Simplify post_store.go to use PostgreSQL-only code paths:
- Inline getParentsPostsPostgreSQL into getParentsPosts
- Use PostgreSQL TO_CHAR/TO_TIMESTAMP for date formatting in analytics
- Use PostgreSQL array syntax for batch deletes
- Simplify determineMaxPostSize to always use information_schema
- Use PostgreSQL jsonb subtraction for thread participants
- Always execute RefreshPostStats (PostgreSQL materialized views)
- Use materialized views for AnalyticsPostCountsByDay
- Simplify AnalyticsPostCountByTeam to always use countByTeam
* Remove driver checks in channel_store.go
Simplify channel_store.go to use PostgreSQL-only code paths:
- Always use sq.Dollar.ReplacePlaceholders for UNION queries
- Use PostgreSQL LEFT JOIN for retention policy exclusion
- Use PostgreSQL jsonb @> operator for access control policy imports
- Simplify buildLIKEClause to always use LOWER() for case-insensitive search
- Simplify buildFulltextClauseX to always use PostgreSQL to_tsvector/to_tsquery
- Simplify searchGroupChannelsQuery to use ARRAY_TO_STRING/ARRAY_AGG
* Remove driver checks in file_info_store.go
Simplify file_info_store.go to use PostgreSQL-only code paths:
- Always use PostgreSQL to_tsvector/to_tsquery for file search
- Use file_stats materialized view for CountAll()
- Use file_stats materialized view for GetStorageUsage() when not including deleted
- Always execute RefreshFileStats() for materialized view refresh
* Remove driver checks in attributes_store.go
Simplify attributes_store.go to use PostgreSQL-only code paths:
- Always execute RefreshAttributes() for materialized view refresh
- Remove isPostgreSQL parameter from generateSearchQueryForExpression
- Always use PostgreSQL LOWER() LIKE LOWER() syntax for case-insensitive search
* Remove driver checks in retention_policy_store.go
Simplify retention_policy_store.go to use PostgreSQL-only code paths:
- Remove isPostgres parameter from scanRetentionIdsForDeletion
- Always use pq.Array for scanning retention IDs
- Always use pq.Array for inserting retention IDs
- Remove unused json import
* Remove driver checks in property stores
Simplify property_field_store.go and property_value_store.go to use
PostgreSQL-only code paths:
- Always use PostgreSQL type casts (::text, ::jsonb, ::bigint, etc.)
- Remove isPostgres variable and conditionals
* Remove driver checks in channel_member_history_store.go
Simplify PermanentDeleteBatch to use PostgreSQL-only code path:
- Always use ctid-based subquery for DELETE with LIMIT
* Remove remaining driver checks in user_store.go
Simplify user_store.go to use PostgreSQL-only code paths:
- Use LEFT JOIN for bot exclusion in AnalyticsActiveCountForPeriod
- Use LEFT JOIN for bot exclusion in IsEmpty
* Simplify fulltext search by consolidating buildFulltextClause functions
Remove convertMySQLFullTextColumnsToPostgres and consolidate
buildFulltextClause and buildFulltextClauseX into a single function
that takes variadic column arguments and returns sq.Sqlizer.
* Simplify SQL stores leveraging PostgreSQL-only support
- Simplify UpdateMembersRole in channel_store.go and team_store.go
to use UPDATE...RETURNING instead of SELECT + UPDATE
- Simplify GetPostReminders in post_store.go to use DELETE...RETURNING
- Simplify DeleteOrphanedRows queries by removing MySQL workarounds
for subquery locking issues
- Simplify UpdateUserLastSyncAt to use UPDATE...FROM...RETURNING
instead of fetching user first then updating
- Remove MySQL index hint workarounds in ORDER BY clauses
- Update outdated comments referencing MySQL
- Consolidate buildFulltextClause and remove convertMySQLFullTextColumnsToPostgres
* Remove MySQL-specific test artifacts
- Delete unused MySQLStopWords variable and stop_word.go file
- Remove redundant testSearchEmailAddressesWithQuotes test
(already covered by testSearchEmailAddresses)
- Update comment that referenced MySQL query planning
* Remove MySQL references from server code outside sqlstore
- Update config example and DSN parsing docs to reflect PostgreSQL-only support
- Remove mysql:// scheme check from IsDatabaseDSN
- Simplify SanitizeDataSource to only handle PostgreSQL
- Remove outdated MySQL comments from model and plugin code
* Remove MySQL references from test files
- Update test DSNs to use PostgreSQL format
- Remove dead mysql-replica flag and replicaFlag variable
- Simplify tests that had MySQL/PostgreSQL branches
* Update docs and test config to use PostgreSQL
- Update mmctl config set example to use postgres driver
- Update test-config.json to use PostgreSQL DSN format
* Remove MySQL migration scripts, test data, and docker image
Delete MySQL-related files that are no longer needed:
- ESR upgrade scripts (esr.*.mysql.*.sql)
- MySQL schema dumps (mattermost-mysql-*.sql)
- MySQL replication test scripts (replica-*.sh, mysql-migration-test.sh)
- MySQL test warmup data (mysql_migration_warmup.sql)
- MySQL docker image reference from mirror-docker-images.json
* Remove MySQL references from webapp
- Simplify minimumHashtagLength description to remove MySQL-specific configuration note
- Remove unused HIDE_MYSQL_STATS_NOTIFICATION preference constant
- Update en.json i18n source file
* clean up e2e-tests
* rm server/tests/template.load
* Use teamMemberSliceColumns() in UpdateMembersRole RETURNING clause
Refactor to use the existing helper function instead of hardcoding
the column names, ensuring consistency if the columns are updated.
* u.id -> u.Id
* address code review feedback
---------
Co-authored-by: Mattermost Build <build@mattermost.com>