* Add read receipt store for burn on read message types
* update mocks
* fix invalidation target
* have consistent case on index creation
* Add temporary posts table
* add mock
* add transaction support
* reflect review comments
* wip: Add reveal endpoint
* user check error id instead
* wip: Add ws events and cleanup for burn on read posts
* add burn endpoint for explicitly burning messages
* add translations
* Added logic to associate files of BoR post with the post
* Added test
* fixes
* disable pinning posts and review comments
* MM-66594 - Burn on read UI integration (#34647)
* MM-66244 - add BoR visual components to message editor
* MM-66246 - BoR visual indicator for sender and receiver
* MM-66607 - bor - add timer countdown and autodeletion
* add the system console max time to live config
* use the max expire at and create global scheduler to register bor messages
* use seconds for BoR config values in BE
* implement the read by text shown in the tooltip logic
* unestack the posts from same receiver and BoR and fix styling
* avoid opening reply RHS
* remove unused dispatchers
* persis the BoR label in the drafts
* move expiration value to metadata
* adjust unit tests to metadata insted of props
* code clean up and some performance improvements; add period grace for deletion too
* adjust migration serie number
* hide bor messages when config is off
* performance improvements on post component and code clean up
* keep bor existing post functionality if config is disabled
* Add read receipt store for burn on read message types
* Add temporary posts table
* add transaction support
* reflect review comments
* wip: Add reveal endpoint
* user check error id instead
* wip: Add ws events and cleanup for burn on read posts
* avoid reacting to unrevealed bor messages
* adjust migration number
* Add read receipt store for burn on read message types
* have consistent case on index creation
* Add temporary posts table
* add mock
* add transaction support
* reflect review comments
* wip: Add reveal endpoint
* user check error id instead
* wip: Add ws events and cleanup for burn on read posts
* add burn endpoint for explicitly burning messages
* adjust post reveal and type with backend changes
* use real config values, adjust icon usage and style
* adjust the delete from from sender and receiver
* improve self deleting logic by placing in badge, use burn endpoint
* adjust websocket events handling for the read by sender label information
* adjust styling for concealed and error state
* update burn-on-read post event handling for improved recipient tracking and multi-device sync
* replace burn_on_read with type in database migrations and model
* remove burn_on_read metadata from PostMetadata and related structures
* Added logic to associate files of BoR post with the post
* Added test
* adjust migration name and fix linter
* Add read receipt store for burn on read message types
* update mocks
* have consistent case on index creation
* Add temporary posts table
* add mock
* add transaction support
* reflect review comments
* wip: Add reveal endpoint
* user check error id instead
* wip: Add ws events and cleanup for burn on read posts
* add burn endpoint for explicitly burning messages
* Added logic to associate files of BoR post with the post
* Added test
* disable pinning posts and review comments
* show attachment on bor reveal
* remove unused translation
* Enhance burn-on-read post handling and refine previous post ID retrieval logic
* adjust the returning chunk to work with bor messages
* read temp post from master db
* read from master
* show the copy link button to the sender
* revert unnecessary check
* restore correct json tag
* remove unused error handling and clarify burn-on-read comment
* improve type safety and use proper selectors
* eliminate code duplication in deletion handler
* optimize performance and add documentation
* delete bor message for sender once all receivers reveal it
* add burn on read to scheduled posts
* add feature enable check
* use master to avoid all read recipients race condition
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
Co-authored-by: Ibrahim Serdar Acikgoz <serdaracikgoz86@gmail.com>
Co-authored-by: Harshil Sharma <harshilsharma63@gmail.com>
* squash migrations into single file
* add configuration for the scheduler
* don't run messagehasbeenposted hook
* remove parallel tests on burn on read
* add clean up for closing opened modals from previous tests
* simplify delete menu item rendering
* add cleanup step to close open modals after each test to prevent pollution
* streamline delete button visibility logic for Burn on Read posts
* improve reliability of closing post menu and modals by using body ESC key
---------
Co-authored-by: Harshil Sharma <harshilsharma63@gmail.com>
Co-authored-by: Pablo Vélez <pablovv2012@gmail.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
When we last bumped dependencies in https://github.com/mattermost/mattermost/pull/30005, `assert.NotSame` for maps started failing because of the change in https://github.com/stretchr/testify/issues/1661. The reality was that the previous assertion was silently skipped, and just now reporting as much.
Here's an illustrative example:
```go
package main
import (
"maps"
"testing"
"github.com/stretchr/testify/assert"
)
func TestClonedMapsAreNotSame(t *testing.T) {
original := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
cloned := maps.Clone(original)
assert.NotSame(t, original, cloned)
}
func TestSameMaps(t *testing.T) {
original := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
cloned := original
assert.Same(t, original, cloned)
cloned["d"] = 4
assert.Same(t, original, cloned)
}
```
which fails with the following after the original dependency update:
```
--- FAIL: TestClonedMapsAreNotSame (0.00s)
main_test.go:19:
Error Trace: /Users/jesse/tmp/testify/main_test.go:19
Error: Both arguments must be pointers
Test: TestClonedMapsAreNotSame
--- FAIL: TestSameMaps (0.00s)
main_test.go:30:
Error Trace: /Users/jesse/tmp/testify/main_test.go:30
Error: Both arguments must be pointers
Test: TestSameMaps
main_test.go:33:
Error Trace: /Users/jesse/tmp/testify/main_test.go:33
Error: Both arguments must be pointers
Test: TestSameMaps
FAIL
FAIL testassertequal 0.149s
FAIL
```
However, instead of fixing the underlying issue, we took the address of those variables and kept using `assert.Same`. This isn't meaningful, since it doesn't directly compare the underlying pointers of the map objects in question, just the address of the pointers to those maps. Here's the output after taking the address (e.g. `&original` and `&cloned`):
```
--- FAIL: TestSameMaps (0.00s)
main_test.go:30:
Error Trace: /Users/jesse/tmp/testify/main_test.go:30
Error: Not same:
expected: 0x14000070170 &map[string]int{"a":1, "b":2, "c":3}
actual : 0x14000070178 &map[string]int{"a":1, "b":2, "c":3}
Test: TestSameMaps
main_test.go:33:
Error Trace: /Users/jesse/tmp/testify/main_test.go:33
Error: Not same:
expected: 0x14000070170 &map[string]int{"a":1, "b":2, "c":3, "d":4}
actual : 0x14000070178 &map[string]int{"a":1, "b":2, "c":3, "d":4}
Test: TestSameMaps
FAIL
FAIL testassertequal 0.157s
FAIL
```
They are obviously the same map, since modifying `cloned` modified the
original, yet `assert.Same` thinks they are different (because the
pointe values are indeed different). (`assert.NotSame` "passes", but for
the wrong reasons.)
To fix this, introduce `model.AssertNotSameMap` to check this correctly.
The searchArchivedChannelsForTeam functionality has been superseded by the
searchAllChannels API with include_deleted parameter. The Browse Channels modal
and other UI components now use the modern searchAllChannels approach.
Fixes: https://mattermost.atlassian.net/browse/MM-64395
* pin to ubuntu-24.04
* always use FIPS compatible Postgres settings
* use sha256 for remote cluster IDs
* use sha256 for client config hash
* rework S3 backend to be FIPS compatible
* skip setup-node during build, since already in container
* support FIPS builds
* Dockerfile for FIPS image, using glibc-openssl-fips
* workaround entrypoint inconsistencies
* authenticate to DockerHub
* fix FIPS_ENABLED, add test-mmctl-fips
* decouple check-mattermost-vet from test/build steps
* fixup! decouple check-mattermost-vet from test/build steps
* only build-linux-amd64 for fips
* rm entrypoint workaround
* tweak comment grammar
* rm unused Dockerfile.fips (for now)
* ignore gpg import errors, since would fail later anyway
* for fips, only make package-linux-amd64
* set FIPS_ENABLED for build step
* Add a FIPS-specific list of prepackaged plugins
Note that the names are still temporary, since they are not uploaded to
S3 yet. We may need to tweak them when that happens.
* s/golangci-lint/check-style/
This ensures we run all the `check-style` checks: previously,
`modernize` was missing.
* pin go-vet to @v2, remove annoying comment
* add -fips to linux-amd64.tz.gz package
* rm unused setup-chainctl
* use BUILD_TYPE_NAME instead
* mv fips build to enterprise-only
* fixup! use BUILD_TYPE_NAME instead
* temporarily pre-package no plugins for FIPS
* split package-cleanup
* undo package-cleanup, just skip ARM, also test
* skip arm for FIPS in second target too
* fmt Makefile
* Revert "rm unused Dockerfile.fips (for now)"
This reverts commit 601e37e0ff.
* reintroduce Dockerfile.fips and align with existing Dockerfile
* s/IMAGE/BUILD_IMAGE/
* bump the glibc-openssl-fips version
* rm redundant comment
* fix FIPS checks
* set PLUGIN_PACKAGES empty until prepackaged plugins ready
* upgrade glibc-openssl-fips, use non-dev version for final stage
* another BUILD_IMAGE case
* Prepackage the FIPS versions of plugins
* relocate FIPS_ENABLED initialization before use
* s/Config File MD5/Config File Hash/
* Update the FIPS plugin names and encode the + sign
* add /var/tmp for local socket manipulation
---------
Co-authored-by: Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
* Standardize request.CTX parameter naming to rctx
- Migrate 886 request.CTX parameters across 147 files to use consistent 'rctx' naming
- Updated function signatures from 'c', 'ctx', and 'cancelContext' to 'rctx'
- Updated function bodies to reference the new parameter names
- Preserved underscore parameters unchanged as they are unused
- Fixed method receiver context issue in store.go
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Use request.CTX interface in batch worker
* Manual fixes
* Fix parameter naming
* Add linter check
---------
Co-authored-by: Claude <noreply@anthropic.com>
- Test Elasticsearch configuration when indexing is enabled
- Capture configuration errors in support packet diagnostics
- Add comprehensive test coverage for Elasticsearch scenarios
- Fix LDAP mock cleanup in existing tests
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude <noreply@anthropic.com>
- Remove NotificationLogSettings configuration entirely
- Add new notification-specific log levels (NotificationError, NotificationWarn, NotificationInfo, NotificationDebug, NotificationTrace)
- Consolidate all notification logs into standard mattermost.log file
- Update all notification logging code to use new multi-level logging (MlvlNotification*)
- Remove notification logger infrastructure and support packet integration
- Update test configurations and remove deprecated functionality tests
- Add comprehensive tests for new notification log levels
This change simplifies log analysis by unifying all application logging while maintaining flexibility through Advanced Logging configuration for administrators who need separate notification logs.
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
When a user disconnects from the hub, we would spawn off a goroutine
which would make a cluster request, and then update the user status
as offline in the DB.
This was another case of unbounded concurrency where the number of
goroutines spawned was user controlled. Therefore, we would see
a clear spike in DB connections on master when a lot of users
would suddenly disconnect.
To fix this, we implement concurrency control in two areas:
1. In making the cluster request. We implement a counting semaphore
per-hub to avoid making unbounded cluster requests.
2. We use a buffered channel with a periodic flusher to process
status updates.
We also add a new store method to upsert multiple statuses
in a single query. The statusUpdateThreshold is set to 32, which means
no more than 32 rows will be upserted at one time, keeping the
SQL query load reasonable.
https://mattermost.atlassian.net/browse/MM-64298
```release-note
We improve DB connection spikes on user disconnect
by processing status updates in batches.
```
* Adds support for GMs in shared channels
* Fix linter
* Remove creatorID from slack call
---------
Co-authored-by: Miguel de la Cruz <miguel@ctrlz.es>
* Upgrade Go to 1.24.3
Updates the following files:
- server/.go-version: 1.23.9 → 1.24.3
- server/build/Dockerfile.buildenv: golang:1.23.9-bullseye → golang:1.24.3-bullseye
- server/go.mod: go 1.23.0 → go 1.24.3, toolchain go1.23.9 → go1.24.3
- server/public/go.mod: go 1.23.0 → go 1.24.3, toolchain go1.23.9 → go1.24.3
Also fixes non-constant format string errors introduced by Go 1.24.3's stricter format string checking:
- Added response() helper function in slashcommands/util.go for simple string responses
- Removed unused responsef() function from slashcommands/util.go
- Replaced responsef() with response() for translated strings that don't need formatting
- Fixed fmt.Errorf and fmt.Fprintf calls to use proper format verbs instead of string concatenation
- Updated marketplace buildURL to handle format strings conditionally
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update generated mocks for Go 1.24.3
Regenerated mocks using mockery v2.53.4 to ensure compatibility with Go 1.24.3.
This addresses mock generation failures that occurred with the Go upgrade.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update to bookworm and fix non-existent sha
Signed-off-by: Stavros Foteinopoulos <stafot@gmail.com>
* fix non-constant format string
---------
Signed-off-by: Stavros Foteinopoulos <stafot@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Stavros Foteinopoulos <stafot@gmail.com>
We've recently spent some effort improving websocket reconnection logic. With this commit, I've augmented the websocket reconnect metric to include a disconnect reason. This will help us measure the impact of these changes in production.
* TestPool
* Store infra
* Store tests updates
* Bump maximum concurrent postgres connections
* More infra
* channels/jobs
* channels/app
* channels/api4
* Protect i18n from concurrent access
* Replace some use of os.Setenv
* Remove debug
* Lint fixes
* Fix more linting
* Fix test
* Remove use of Setenv in drafts tests
* Fix flaky TestWebHubCloseConnOnDBFail
* Fix merge
* [MM-62408] Add CI job to generate test coverage (#30284)
* Add CI job to generate test coverage
* Remove use of Setenv in drafts tests
* Fix flaky TestWebHubCloseConnOnDBFail
* Fix more Setenv usage
* Fix more potential flakyness
* Remove parallelism from flaky test
* Remove conflicting env var
* Fix
* Disable parallelism
* Test atomic covermode
* Disable parallelism
* Enable parallelism
* Add upload coverage step
* Fix codecov.yml
* Add codecov.yml
* Remove redundant workspace field
* Add Parallel() util methods and refactor
* Fix formatting
* More formatting fixes
* Fix reporting
* reject MySQL with the enterprise advanced license
If a user attempts to set an Enterprise Advanced License while
configured with MySQL, reject the license. This SKU is not compatible
with MYSQL.
* fix trial typo
* suppress trial banner if MySQL
* Update server/channels/app/platform/license_test.go
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix types
* suppress mysql from show start trial modal
* Skip MySQL-incompatible tests for access control and channel banner features
Skip the following tests when running with MySQL database:
- Access control policy tests (create, get, delete, check/test expressions, search, assign/unassign, get channels)
- Channel banner tests in TestPatchChannel and TestCanEditChannelBanner
These features are not supported on MySQL and the tests would fail.
Tests will continue to run normally on PostgreSQL.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Skip TestSearchChannelsForAccessControlPolicy subtest for MySQL
Add MySQL skip logic to the "SearchChannelsForAccessControlPolicy with regular user"
subtest as this access control feature is not supported on MySQL.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* reject trial license requests for MySQL
* return false on sku + mysql match, even if logger is nil
* Fix MySQL trial license tests to skip appropriately based on database driver
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
* rm "No TEST_DATABASE... override" log message
Let's only log if this value is actually overridden.
* rm "(Created|Dropped) temporary database" message
* only log "Pinging SQL" on subsequent attempts
* disable morph logging from TestMain
* Fix style issues in store test files
- Add missing parameter to migrate() function calls in tests
- Remove unused log function in settings.go
- Fix formatting with go fmt
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* within sqlstore, use "enable" vs "disable" for clarity
* remove trailing newline from morph logs
---------
Co-authored-by: Claude <noreply@anthropic.com>
A recent change to the enterprise cluster code introduced a change to the enterprise API interface. GetClusterInfos() can now return an error. This commit introduces code to handle that error.
We switch to using iterators introduced in Go 1.23
to make iteration alloc-free and fast. And since
element removal is allowed while iterating a map,
this also means we don't need to even copy the slice
any more.
While here, we also address the comment https://github.com/mattermost/mattermost/pull/30178#discussion_r1954862151.
I have simply gone back to using []string as the map
entry rather than a type alias or a redirection with
a struct.
https://mattermost.atlassian.net/browse/MM-63130
```release-note
NONE
```
* Changed back nil to len
```release-note
NONE
```
* fixing unused assignment
```release-note
NONE
```
* add benchmark
```
goos: linux
goarch: amd64
pkg: github.com/mattermost/mattermost/server/v8/channels/app/platform
cpu: Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz
│ old.txt │ new.txt │
│ sec/op │ sec/op vs base │
HubConnIndexIterator/2_users-8 93.53n ± 1% 38.09n ± 1% -59.27% (p=0.000 n=10)
HubConnIndexIterator/3_users-8 106.30n ± 0% 38.41n ± 1% -63.86% (p=0.000 n=10)
HubConnIndexIterator/4_users-8 111.30n ± 1% 38.66n ± 1% -65.27% (p=0.000 n=10)
geomean 103.4n 38.39n -62.89%
│ old.txt │ new.txt │
│ B/op │ B/op vs base │
HubConnIndexIterator/2_users-8 16.00 ± 0% 24.00 ± 0% +50.00% (p=0.000 n=10)
HubConnIndexIterator/3_users-8 24.00 ± 0% 24.00 ± 0% ~ (p=1.000 n=10) ¹
HubConnIndexIterator/4_users-8 32.00 ± 0% 24.00 ± 0% -25.00% (p=0.000 n=10)
geomean 23.08 24.00 +4.00%
¹ all samples are equal
│ old.txt │ new.txt │
│ allocs/op │ allocs/op vs base │
HubConnIndexIterator/2_users-8 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹
HubConnIndexIterator/3_users-8 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹
HubConnIndexIterator/4_users-8 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹
geomean 1.000 1.000 +0.00%
¹ all samples are equal
```
```release-note
NONE
```
* ForChannel test as well
```release-note
NONE
```
* review comments
```release-note
NONE
```
* fix lint errors
```release-note
NONE
```
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
* fix: hanlde error from InvalidateAllCaches in slack.go
* change signature of InvalidateAllCaches to *model.AppError
* return err from InvalidateAllCaches everywhere
* Formatting
---------
Co-authored-by: Ben Schumacher <ben.schumacher@mattermost.com>
* Adds direct participants to the channel invite
The channel invite now contains the sanitized users that are local to
the node that is sending the invite. In the event that the receiving
server doesn't have those users in its local database, it can create
them from the invite and correctly generate the DM or GM with them as
members.
* Use IsRemote instead of directly checking user attributes
---------
Co-authored-by: Miguel de la Cruz <miguel@ctrlz.es>
Co-authored-by: Mattermost Build <build@mattermost.com>
If the deadQueue was full, we would be incorrectly sending
the wrong index for dqPtr. Fixed that and added a test case.
https://mattermost.atlassian.net/browse/MM-63304
```release-note
NONE
```
* MM-61947 Run DND expiry job more often and round expiry time to match interval
* Move comment to make it godoc-compatible
* Change truncateDNDEndTime to work with seconds
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
When Channel iteration mode is enabled, we need to ensure that
channel scoped events do not fall through to the connIndex.All()
condition. This is possible because there are multiple hubs
in a given system. So a single event will flow through all of them
and in some hubs, a channel scoped event might not have any connections.
In that case, we need to stop processing further.
https://mattermost.atlassian.net/browse/MM-62960
```release-note
NONE
```
When we added iteration by channelID, this was a known tradeoff during that.
However, it has been observed that the regular connection removal function
creates considerable blocking of the processing loop, leading to high
CPU usage and API latencies.
To fix this, we add a reverse mapping of channelIDs to connections
and their positions in the slice. This helps us to remove the connection
from the slice without iteration.
Unfortunately, this still needs to iterate through all channelIDs
during invalidation of the channel member cache. However, the user
cache invalidation is not a regular activity. So it should be an acceptable
tradeoff to make.
https://mattermost.atlassian.net/browse/MM-62960
```release-note
A new config knob ServiceSettings.EnableWebHubChannelIteration which allows a user to control the performance of websocket broadcasting. By default, this setting is turned off. If it is turned on, it improves the websocket broadcasting performance at the expense of poor performance when users join/leave a channel. It is not recommended to turn it on unless you have atleast 200,000 concurrent users actively using MM.
```
Co-authored-by: Mattermost Build <build@mattermost.com>