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
2 changes: 1 addition & 1 deletion .github/workflows/server-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ jobs:
services:
# make default-roles-permissions snapshots a live database.
postgres:
image: postgres:14
image: postgres:15
env:
POSTGRES_USER: mmuser
POSTGRES_PASSWORD: mostest
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ Other install guides:
- [Ubuntu 20.04 LTS](https://docs.mattermost.com/install/installing-ubuntu-2004-LTS.html)
- [Kubernetes](https://docs.mattermost.com/install/install-kubernetes.html)
- [Helm](https://docs.mattermost.com/install/install-kubernetes.html#installing-the-operators-via-helm)
- [Debian Buster](https://docs.mattermost.com/install/install-debian.html)
- [RHEL 8](https://docs.mattermost.com/install/install-rhel-8.html)
- [More server install guides](https://docs.mattermost.com/guides/deployment.html)

## Native mobile and desktop apps
Expand Down
2 changes: 1 addition & 1 deletion e2e-tests/.ci/server.generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ $(for service in $ENABLED_DOCKER_SERVICES; do
$(if mme2e_is_token_in_list "postgres" "$ENABLED_DOCKER_SERVICES"; then
echo '
postgres:
image: mattermostdevelopment/mirrored-postgres:14
image: mattermostdevelopment/mirrored-postgres:15
restart: "no"
network_mode: host
networks: !reset []
Expand Down
2 changes: 0 additions & 2 deletions e2e-tests/playwright/lib/src/server/default_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -775,8 +775,6 @@
ImageProxySettings: {
Enable: false,
ImageProxyType: 'local',
RemoteImageProxyURL: '',
RemoteImageProxyOptions: '',
},
CloudSettings: {
CWSURL: 'https://customers.mattermost.com',
Expand Down Expand Up @@ -817,7 +815,7 @@
ManagedChannelCategories: false,
SessionAttributes: false,
DiscoverableChannels: false,
MobileEphemeralMode: false,

Check warning on line 818 in e2e-tests/playwright/lib/src/server/default_config.ts

View workflow job for this annotation

GitHub Actions / check

File has too many lines (906). Maximum allowed is 800
PropertyFieldRank: false,
TeamMembershipAccessControl: true,
MmBlocksEnabled: true,
Expand Down
1 change: 0 additions & 1 deletion server/.golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,6 @@ linters:
platform/services/cache/lru_test.go|\
platform/services/docextractor/combine.go|\
platform/services/docextractor/pdf.go|\
platform/services/imageproxy/atmos_camo_test.go|\
platform/services/imageproxy/local.go|\
platform/services/imageproxy/local_test.go|\
platform/services/remotecluster/invitation.go|\
Expand Down
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.26.4@sha256:6c979d9bf17e17dcd52fa052867f2910a4b9bca3f10d4c439e0b8f233a53d426
FROM golang:1.26.4-bookworm@sha256:b305420a68d0f229d91eb3b3ed9e519fcf2cf5461da4bef997bf927e8c0bfd2b
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/docker-compose.common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ x-logging: &default-logging

services:
postgres:
image: "postgres:14"
image: "postgres:15"
logging: *default-logging
restart: always
networks:
Expand Down
21 changes: 0 additions & 21 deletions server/channels/api4/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,27 +43,6 @@ func TestGetImage(t *testing.T) {
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
})

t.Run("atmos/camo", func(t *testing.T) {
imageURL := "http://foo.bar/baz.gif"
proxiedURL := "https://proxy.foo.bar/83d4d9ac78b76ce425ea67038826df867c62cc5c/687474703a2f2f666f6f2e6261722f62617a2e676966"

th.App.UpdateConfig(func(cfg *model.Config) {
cfg.ImageProxySettings.Enable = new(true)
cfg.ImageProxySettings.ImageProxyType = new("atmos/camo")
cfg.ImageProxySettings.RemoteImageProxyOptions = new("7e5f3fab20b94782b43cdb022a66985ef28ba355df2c5d5da3c9a05e4b697bac")
cfg.ImageProxySettings.RemoteImageProxyURL = new("https://proxy.foo.bar")
})

r, err := http.NewRequest("GET", th.Client.APIURL+"/image?url="+url.QueryEscape(imageURL), nil)
require.NoError(t, err)
r.Header.Set(model.HeaderAuth, th.Client.AuthType+" "+th.Client.AuthToken)

resp, err := th.Client.HTTPClient.Do(r)
require.NoError(t, err)
assert.Equal(t, http.StatusFound, resp.StatusCode)
assert.Equal(t, proxiedURL, resp.Header.Get("Location"))
})

t.Run("local", func(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) {
cfg.ImageProxySettings.Enable = new(true)
Expand Down
4 changes: 1 addition & 3 deletions server/channels/app/post_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,7 @@ func (s *Server) initPostMetadata() {
// Dump any cached links if the proxy settings have changed so image URLs can be updated
s.platform.AddConfigListener(func(before, after *model.Config) {
if (before.ImageProxySettings.Enable != after.ImageProxySettings.Enable) ||
(before.ImageProxySettings.ImageProxyType != after.ImageProxySettings.ImageProxyType) ||
(before.ImageProxySettings.RemoteImageProxyURL != after.ImageProxySettings.RemoteImageProxyURL) ||
(before.ImageProxySettings.RemoteImageProxyOptions != after.ImageProxySettings.RemoteImageProxyOptions) {
(before.ImageProxySettings.ImageProxyType != after.ImageProxySettings.ImageProxyType) {
if err := platform.PurgeLinkCache(); err != nil {
mlog.Warn("Failed to remove cached links when the proxy settings changed", mlog.Err(err))
}
Expand Down
4 changes: 1 addition & 3 deletions server/channels/app/post_metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1035,9 +1035,7 @@ func TestPreparePostForClientWithImageProxy(t *testing.T) {
*cfg.ServiceSettings.SiteURL = "http://mymattermost.com"
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost,127.0.0.1"
*cfg.ImageProxySettings.Enable = true
*cfg.ImageProxySettings.ImageProxyType = "atmos/camo"
*cfg.ImageProxySettings.RemoteImageProxyURL = "https://127.0.0.1"
*cfg.ImageProxySettings.RemoteImageProxyOptions = model.NewTestPassword()
*cfg.ImageProxySettings.ImageProxyType = "local"
})

th.App.ch.imageProxy = imageproxy.MakeImageProxy(th.Server.platform, th.Server.HTTPService(), th.Server.Log())
Expand Down
50 changes: 3 additions & 47 deletions server/channels/app/post_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -894,48 +894,12 @@ func TestImageProxy(t *testing.T) {

th.App.ch.imageProxy = imageproxy.MakeImageProxy(th.Server.platform, th.Server.HTTPService(), th.Server.Log())

testHMACKey := model.NewTestPassword()

for name, tc := range map[string]struct {
ProxyType string
ProxyURL string
ProxyOptions string
ImageURL string
ProxiedImageURL string
ProxiedRemovedImageURL string
}{
"atmos/camo": {
ProxyType: model.ImageProxyTypeAtmosCamo,
ProxyURL: "https://127.0.0.1",
ProxyOptions: testHMACKey,
ImageURL: "http://mydomain.com/myimage",
ProxiedRemovedImageURL: "http://mydomain.com/myimage",
ProxiedImageURL: "http://mymattermost.com/api/v4/image?url=http%3A%2F%2Fmydomain.com%2Fmyimage",
},
"atmos/camo_SameSite": {
ProxyType: model.ImageProxyTypeAtmosCamo,
ProxyURL: "https://127.0.0.1",
ProxyOptions: testHMACKey,
ImageURL: "http://mymattermost.com/myimage",
ProxiedRemovedImageURL: "http://mymattermost.com/myimage",
ProxiedImageURL: "http://mymattermost.com/myimage",
},
"atmos/camo_PathOnly": {
ProxyType: model.ImageProxyTypeAtmosCamo,
ProxyURL: "https://127.0.0.1",
ProxyOptions: testHMACKey,
ImageURL: "/myimage",
ProxiedRemovedImageURL: "http://mymattermost.com/myimage",
ProxiedImageURL: "http://mymattermost.com/myimage",
},
"atmos/camo_EmptyImageURL": {
ProxyType: model.ImageProxyTypeAtmosCamo,
ProxyURL: "https://127.0.0.1",
ProxyOptions: testHMACKey,
ImageURL: "",
ProxiedRemovedImageURL: "",
ProxiedImageURL: "",
},
"local": {
ProxyType: model.ImageProxyTypeLocal,
ImageURL: "http://mydomain.com/myimage",
Expand Down Expand Up @@ -965,8 +929,6 @@ func TestImageProxy(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) {
cfg.ImageProxySettings.Enable = new(true)
cfg.ImageProxySettings.ImageProxyType = new(tc.ProxyType)
cfg.ImageProxySettings.RemoteImageProxyOptions = new(tc.ProxyOptions)
cfg.ImageProxySettings.RemoteImageProxyURL = new(tc.ProxyURL)
})

post := &model.Post{
Expand Down Expand Up @@ -1164,9 +1126,7 @@ func TestCreatePost(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.SiteURL = "http://mymattermost.com"
*cfg.ImageProxySettings.Enable = true
*cfg.ImageProxySettings.ImageProxyType = "atmos/camo"
*cfg.ImageProxySettings.RemoteImageProxyURL = "https://127.0.0.1"
*cfg.ImageProxySettings.RemoteImageProxyOptions = model.NewTestPassword()
*cfg.ImageProxySettings.ImageProxyType = "local"
})

th.App.ch.imageProxy = imageproxy.MakeImageProxy(th.Server.platform, th.Server.HTTPService(), th.Server.Log())
Expand Down Expand Up @@ -2029,9 +1989,7 @@ func TestPatchPost(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.SiteURL = "http://mymattermost.com"
*cfg.ImageProxySettings.Enable = true
*cfg.ImageProxySettings.ImageProxyType = "atmos/camo"
*cfg.ImageProxySettings.RemoteImageProxyURL = "https://127.0.0.1"
*cfg.ImageProxySettings.RemoteImageProxyOptions = model.NewTestPassword()
*cfg.ImageProxySettings.ImageProxyType = "local"
})

th.App.ch.imageProxy = imageproxy.MakeImageProxy(th.Server.platform, th.Server.HTTPService(), th.Server.Log())
Expand Down Expand Up @@ -2490,9 +2448,7 @@ func TestUpdatePost(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.SiteURL = "http://mymattermost.com"
*cfg.ImageProxySettings.Enable = true
*cfg.ImageProxySettings.ImageProxyType = "atmos/camo"
*cfg.ImageProxySettings.RemoteImageProxyURL = "https://127.0.0.1"
*cfg.ImageProxySettings.RemoteImageProxyOptions = model.NewTestPassword()
*cfg.ImageProxySettings.ImageProxyType = "local"
})

th.App.ch.imageProxy = imageproxy.MakeImageProxy(th.Server.platform, th.Server.HTTPService(), th.Server.Log())
Expand Down
4 changes: 1 addition & 3 deletions server/channels/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -598,9 +598,7 @@ func NewServer(options ...Option) (*Server, error) {
// Dump the image cache if the proxy settings have changed. (need switch URLs to the correct proxy)
s.platform.AddConfigListener(func(oldCfg, newCfg *model.Config) {
if (oldCfg.ImageProxySettings.Enable != newCfg.ImageProxySettings.Enable) ||
(oldCfg.ImageProxySettings.ImageProxyType != newCfg.ImageProxySettings.ImageProxyType) ||
(oldCfg.ImageProxySettings.RemoteImageProxyURL != newCfg.ImageProxySettings.RemoteImageProxyURL) ||
(oldCfg.ImageProxySettings.RemoteImageProxyOptions != newCfg.ImageProxySettings.RemoteImageProxyOptions) {
(oldCfg.ImageProxySettings.ImageProxyType != newCfg.ImageProxySettings.ImageProxyType) {
if err = s.openGraphDataCache.Purge(); err != nil {
mlog.Error("Failed to purge Open Graph data cache after config change", mlog.Err(err))
}
Expand Down
4 changes: 4 additions & 0 deletions server/channels/db/migrations/migrations.list
Original file line number Diff line number Diff line change
Expand Up @@ -421,3 +421,7 @@ channels/db/migrations/postgres/000212_add_scheduled_post_recurrence.down.sql
channels/db/migrations/postgres/000212_add_scheduled_post_recurrence.up.sql
channels/db/migrations/postgres/000213_add_scheduled_post_pending_index.down.sql
channels/db/migrations/postgres/000213_add_scheduled_post_pending_index.up.sql
channels/db/migrations/postgres/000214_drop_channelmembers_autotranslation.down.sql
channels/db/migrations/postgres/000214_drop_channelmembers_autotranslation.up.sql
channels/db/migrations/postgres/000215_drop_channelmembers_autotranslation_column.down.sql
channels/db/migrations/postgres/000215_drop_channelmembers_autotranslation_column.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- morph:nontransactional
-- Recreate the partial index on the channelmembers autotranslation column,
-- mirroring migration 000147. Runs after 000215 restores the column.
-- CONCURRENTLY cannot run inside a transaction, so this must be the only
-- statement in the file.
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_channelmembers_autotranslation_enabled
ON channelmembers (channelid)
WHERE autotranslation = true;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- morph:nontransactional
-- Drop the partial index on the deprecated channelmembers autotranslation
-- column ahead of dropping the column itself in 000215. CONCURRENTLY cannot run
-- inside a transaction, so this must be the only statement in the file.
DROP INDEX CONCURRENTLY IF EXISTS idx_channelmembers_autotranslation_enabled;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- Recreate the deprecated channelmembers autotranslation column, mirroring
-- migration 000147. Prior values are not restorable. The partial index is
-- recreated separately in 000214.
ALTER TABLE channelmembers
ADD COLUMN IF NOT EXISTS autotranslation boolean NOT NULL DEFAULT false;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- Drop the deprecated channelmembers autotranslation column (opt-in semantics),
-- replaced by autotranslationdisabled (opt-out) in migration 000151. The partial
-- index on this column is dropped separately in 000214.
ALTER TABLE channelmembers
DROP COLUMN IF EXISTS autotranslation;
2 changes: 1 addition & 1 deletion server/channels/store/sqlstore/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const (
// After 10, it's major and minor only.
// 10.1 would be 100001.
// 9.6.3 would be 90603.
minimumRequiredPostgresVersion = 140000
minimumRequiredPostgresVersion = 150000

migrationsDirectionUp migrationDirection = "up"
migrationsDirectionDown migrationDirection = "down"
Expand Down
19 changes: 14 additions & 5 deletions server/channels/store/sqlstore/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,28 +541,37 @@ func TestCheckVersion(t *testing.T) {
ver: "110001",
wantLog: "Unsupported Postgres version",
wantVersion: "11.1",
wantMinVersion: "14.0",
wantMinVersion: "15.0",
},
{
ver: "130001",
wantLog: "Unsupported Postgres version",
wantVersion: "13.1",
wantMinVersion: "14.0",
wantMinVersion: "15.0",
},
{
ver: "140000",
ver: "140000",
wantLog: "Unsupported Postgres version",
wantVersion: "14.0",
wantMinVersion: "15.0",
},
{
ver: "140019",
ver: "140019",
wantLog: "Unsupported Postgres version",
wantVersion: "14.19",
wantMinVersion: "15.0",
},
{
ver: "150000",
},
{
ver: "150019",
},
{
ver: "90603",
wantLog: "Unsupported Postgres version",
wantVersion: "9.6.3",
wantMinVersion: "14.0",
wantMinVersion: "15.0",
},
{
ver: "12.34.1",
Expand Down
4 changes: 2 additions & 2 deletions server/docker-compose.makefile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ services:
ports:
- "5432:5432"
volumes:
- "postgres-14-data:/var/lib/postgresql/data"
- "postgres-15-data:/var/lib/postgresql/data"
extends:
file: build/docker-compose.common.yml
service: postgres
Expand Down Expand Up @@ -125,4 +125,4 @@ networks:
ip_range: 192.168.254.0/24

volumes:
postgres-14-data:
postgres-15-data:
2 changes: 1 addition & 1 deletion server/docker-compose.pgvector.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
services:
postgres:
# Override the postgres image to use pgvector
image: "pgvector/pgvector:pg14"
image: "pgvector/pgvector:pg15"
# All other settings are inherited from the base service

Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ func TestCheckVersion(t *testing.T) {
wantVersion: "3.0.0",
wantMajor: 3,
},
{
name: "OpenSearch 1 is too old, but allowed",
version: "1.3.0",
wantVersion: "1.3.0",
wantMajor: 1,
wantUnsupported: true,
},
{
name: "OpenSearch 4 is too new, but allowed",
version: "4.0.0",
Expand Down Expand Up @@ -97,6 +104,7 @@ func TestCheckVersion(t *testing.T) {
if tc.wantUnsupported {
assert.Contains(t, buf.String(), "Unsupported OpenSearch version")
assert.Contains(t, buf.String(), fmt.Sprintf(`"version":%q`, tc.wantVersion))
assert.Contains(t, buf.String(), `"min_version":2`)
assert.Contains(t, buf.String(), `"max_version":3`)
} else {
assert.Empty(t, buf.String())
Expand Down
4 changes: 3 additions & 1 deletion server/enterprise/elasticsearch/opensearch/opensearch.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"github.com/mattermost/mattermost/server/v8/platform/services/searchengine"
)

const opensearchMinVersion = 2
const opensearchMaxVersion = 3

var (
Expand Down Expand Up @@ -2369,9 +2370,10 @@ func checkVersion(ctx context.Context, client *opensearchapi.Client, logger mlog
return "", 0, model.NewAppError("Opensearch.checkVersion", "ent.elasticsearch.start.parse_server_version.app_error", map[string]any{"Backend": model.ElasticsearchSettingsOSBackend}, "", http.StatusInternalServerError).Wrap(esErr)
}

if major > opensearchMaxVersion {
if major < opensearchMinVersion || major > opensearchMaxVersion {
logger.Error("Unsupported OpenSearch version. Running an unsupported version may lead to unexpected behaviour.",
mlog.String("version", resp.Version.Number),
mlog.Int("min_version", opensearchMinVersion),
mlog.Int("max_version", opensearchMaxVersion),
)
}
Expand Down
14 changes: 3 additions & 11 deletions server/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -11719,16 +11719,8 @@
"translation": "Invalid timeout value {{.Value}}. Should be a positive number."
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "Invalid RemoteImageProxyOptions for atmos/camo. Must be set to your shared key."
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options_length.app_error",
"translation": "Invalid RemoteImageProxyOptions for atmos/camo: HMAC key must be at least {{.MinLength}} bytes for FIPS compliance."
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_url.app_error",
"translation": "Invalid RemoteImageProxyURL for atmos/camo. Must be set to your shared key."
"id": "model.config.is_valid.atmos_camo_image_proxy_removed.app_error",
"translation": "The 'atmos/camo' image proxy type was removed in Mattermost v12.0. Set ImageProxySettings.ImageProxyType to 'local', or set ImageProxySettings.Enable to false to disable the image proxy."
},
{
"id": "model.config.is_valid.autotranslation.agents.llm_service_id.app_error",
Expand Down Expand Up @@ -11992,7 +11984,7 @@
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "Invalid image proxy type. Must be 'local' or 'atmos/camo'."
"translation": "Invalid image proxy type. Must be 'local'."
},
{
"id": "model.config.is_valid.import.directory.app_error",
Expand Down
Loading
Loading