diff --git a/e2e-tests/cypress/package-lock.json b/e2e-tests/cypress/package-lock.json index 96ba04cb05d..4c0d3d484ee 100644 --- a/e2e-tests/cypress/package-lock.json +++ b/e2e-tests/cypress/package-lock.json @@ -74,7 +74,6 @@ "mochawesome-merge": "4.4.1", "mochawesome-report-generator": "6.2.0", "moment-timezone": "0.6.0", - "mysql": "2.18.1", "path": "0.12.7", "pdf-parse": "1.1.1", "pg": "8.16.3", @@ -4160,16 +4159,6 @@ "tweetnacl": "^0.14.3" } }, - "node_modules/bignumber.js": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", - "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/blob-util": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", @@ -4829,13 +4818,6 @@ "node": ">=6.6.0" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true, - "license": "MIT" - }, "node_modules/cross-env": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.0.0.tgz", @@ -7942,13 +7924,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -9324,29 +9299,6 @@ "dev": true, "license": "MIT" }, - "node_modules/mysql": { - "version": "2.18.1", - "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", - "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", - "dev": true, - "license": "MIT", - "dependencies": { - "bignumber.js": "9.0.0", - "readable-stream": "2.3.7", - "safe-buffer": "5.1.2", - "sqlstring": "2.3.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mysql/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -10214,13 +10166,6 @@ "node": ">= 0.6.0" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "license": "MIT" - }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -10391,29 +10336,6 @@ "dev": true, "license": "MIT" }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -11201,16 +11123,6 @@ "node": ">= 10.x" } }, - "node_modules/sqlstring": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", - "integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/sshpk": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", diff --git a/e2e-tests/cypress/package.json b/e2e-tests/cypress/package.json index b69a094c7a0..c6676f388f1 100644 --- a/e2e-tests/cypress/package.json +++ b/e2e-tests/cypress/package.json @@ -69,7 +69,6 @@ "mochawesome-merge": "4.4.1", "mochawesome-report-generator": "6.2.0", "moment-timezone": "0.6.0", - "mysql": "2.18.1", "path": "0.12.7", "pdf-parse": "1.1.1", "pg": "8.16.3", diff --git a/e2e-tests/cypress/tests/plugins/db_request.js b/e2e-tests/cypress/tests/plugins/db_request.js index 2b91086f278..efca9984d78 100644 --- a/e2e-tests/cypress/tests/plugins/db_request.js +++ b/e2e-tests/cypress/tests/plugins/db_request.js @@ -1,13 +1,6 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -/** - * Functions here are expected to work with MySQL and PostgreSQL (known as dialect). - * When updating this file, make sure to test in both dialect. - * You'll find table and columns names are being converted to lowercase. Reason being is that - * in MySQL, first letter is capitalized. - */ - const mapKeys = require('lodash.mapkeys'); function convertKeysToLowercase(obj) { @@ -33,12 +26,12 @@ const dbGetActiveUserSessions = async ({dbConfig, params: {username, userId, lim try { let user; if (username) { - user = await knexClient(toLowerCase(dbConfig, 'Users')).where('username', username).first(); + user = await knexClient('users').where('username', username).first(); user = convertKeysToLowercase(user); } const now = Date.now(); - const sessions = await knexClient(toLowerCase(dbConfig, 'Sessions')). + const sessions = await knexClient('sessions'). where('userid', user ? user.id : userId). where('expiresat', '>', now). orderBy('lastactivityat', 'desc'). @@ -60,7 +53,7 @@ const dbGetUser = async ({dbConfig, params: {username}}) => { } try { - const user = await knexClient(toLowerCase(dbConfig, 'Users')).where('username', username).first(); + const user = await knexClient('users').where('username', username).first(); return {user: convertKeysToLowercase(user)}; } catch (error) { @@ -75,7 +68,7 @@ const dbGetUserSession = async ({dbConfig, params: {sessionId}}) => { } try { - const session = await knexClient(toLowerCase(dbConfig, 'Sessions')). + const session = await knexClient('sessions'). where('id', '=', sessionId). first(); @@ -92,7 +85,7 @@ const dbUpdateUserSession = async ({dbConfig, params: {sessionId, userId, fields } try { - let user = await knexClient(toLowerCase(dbConfig, 'Users')).where('id', userId).first(); + let user = await knexClient('users').where('id', userId).first(); if (!user) { return {errorMessage: `No user found with id: ${userId}.`}; } @@ -102,12 +95,12 @@ const dbUpdateUserSession = async ({dbConfig, params: {sessionId, userId, fields user = convertKeysToLowercase(user); - await knexClient(toLowerCase(dbConfig, 'Sessions')). + await knexClient('sessions'). where('id', '=', sessionId). where('userid', '=', user.id). update(fieldsToUpdate); - const session = await knexClient(toLowerCase(dbConfig, 'Sessions')). + const session = await knexClient('sessions'). where('id', '=', sessionId). where('userid', '=', user.id). first(); @@ -119,27 +112,11 @@ const dbUpdateUserSession = async ({dbConfig, params: {sessionId, userId, fields } }; -function toLowerCase(config, name) { - if (config.client === 'mysql') { - return name; - } - - return name.toLowerCase(); -} - const dbRefreshPostStats = async ({dbConfig}) => { if (!knexClient) { knexClient = getKnexClient(dbConfig); } - // Only run for PostgreSQL - if (dbConfig.client !== 'postgres') { - return { - skipped: true, - message: 'Refresh post stats is only supported for PostgreSQL', - }; - } - try { await knexClient.raw('REFRESH MATERIALIZED VIEW posts_by_team_day;'); await knexClient.raw('REFRESH MATERIALIZED VIEW bot_posts_by_team_day;'); diff --git a/server/build/Dockerfile.fips b/server/build/Dockerfile.fips index 8e4390eccb0..2521cf245bc 100644 --- a/server/build/Dockerfile.fips +++ b/server/build/Dockerfile.fips @@ -1,5 +1,5 @@ # First stage - FIPS dev image with dependencies for building -FROM cgr.dev/mattermost.com/glibc-openssl-fips:15-dev@sha256:9223f9245fb026a3c255ce9b7028a069fe11432aa7710713a331eaa36f44851c AS builder +FROM cgr.dev/mattermost.com/glibc-openssl-fips:15-dev@sha256:ab5285209fff77fbe56e58aeed6d7f557cf74c6f90d1d8ee26053003f039b419 AS builder # Setting bash as our shell, and enabling pipefail option SHELL ["/bin/bash", "-o", "pipefail", "-c"] diff --git a/server/channels/app/platform/service.go b/server/channels/app/platform/service.go index e2750b0bb4e..c597e0d5c2e 100644 --- a/server/channels/app/platform/service.go +++ b/server/channels/app/platform/service.go @@ -635,7 +635,7 @@ func (ps *PlatformService) LdapDiagnostic() einterfaces.LdapDiagnosticInterface return ps.ldapDiagnostic } -// DatabaseTypeAndSchemaVersion returns the Database type (postgres or mysql) and current version of the schema +// DatabaseTypeAndSchemaVersion returns the database type and current version of the schema func (ps *PlatformService) DatabaseTypeAndSchemaVersion() (string, string, error) { schemaVersion, err := ps.Store.GetDBSchemaVersion() if err != nil { diff --git a/server/channels/app/platform/service_test.go b/server/channels/app/platform/service_test.go index 3198a676a1e..1d940256c60 100644 --- a/server/channels/app/platform/service_test.go +++ b/server/channels/app/platform/service_test.go @@ -242,13 +242,9 @@ func TestDatabaseTypeAndMattermostVersion(t *testing.T) { databaseType, schemaVersion, err := th.Service.DatabaseTypeAndSchemaVersion() require.NoError(t, err) - if *th.Service.Config().SqlSettings.DriverName == model.DatabaseDriverPostgres { - assert.Equal(t, "postgres", databaseType) - } else { - assert.Equal(t, "mysql", databaseType) - } + assert.Equal(t, "postgres", databaseType) - // It's hard to check wheather the schema version is correct or not. + // It's hard to check whether the schema version is correct or not. // So, we just check if it's greater than 1. assert.GreaterOrEqual(t, schemaVersion, strconv.Itoa(1)) } diff --git a/server/channels/app/users/main_test.go b/server/channels/app/users/main_test.go index a98408f771a..ff2890ce6b8 100644 --- a/server/channels/app/users/main_test.go +++ b/server/channels/app/users/main_test.go @@ -4,21 +4,14 @@ package users import ( - "flag" "testing" "github.com/mattermost/mattermost/server/v8/channels/testlib" ) var mainHelper *testlib.MainHelper -var replicaFlag bool func TestMain(m *testing.M) { - if f := flag.Lookup("mysql-replica"); f == nil { - flag.BoolVar(&replicaFlag, "mysql-replica", false, "") - flag.Parse() - } - var options = testlib.HelperOptions{ EnableStore: true, EnableResources: true, diff --git a/server/channels/store/searchlayer/stop_word.go b/server/channels/store/searchlayer/stop_word.go deleted file mode 100644 index 12bcc6e68dc..00000000000 --- a/server/channels/store/searchlayer/stop_word.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package searchlayer - -var MySQLStopWords = []string{"a", "about", "an", "are", "as", "at", "be", "by", "com", "de", "en", "for", "from", "how", "i", "in", "is", "it", "la", "of", - "on", "or", "that", "the", "this", "to", "was", "what", "when", "where", "who", "will", "with", "und", "the", "www"} diff --git a/server/channels/store/searchtest/post_layer.go b/server/channels/store/searchtest/post_layer.go index 7d8eeef4d40..34c8b0be751 100644 --- a/server/channels/store/searchtest/post_layer.go +++ b/server/channels/store/searchtest/post_layer.go @@ -41,17 +41,10 @@ var searchPostStoreTests = []searchTest{ Tags: []string{EnginePostgres}, }, { - // Postgres supports search with and without quotes Name: "Should be able to search for email addresses with or without quotes", Fn: testSearchEmailAddresses, Tags: []string{EnginePostgres, EngineElasticSearch}, }, - { - // MySql supports search with quotes only - Name: "Should be able to search for email addresses with quotes", - Fn: testSearchEmailAddressesWithQuotes, - Tags: []string{EngineElasticSearch}, - }, { Name: "Should be able to search when markdown underscores are applied", Fn: testSearchMarkdownUnderscores, @@ -557,21 +550,6 @@ func testSearchEmailAddresses(t *testing.T, th *SearchTestHelper) { }) } -func testSearchEmailAddressesWithQuotes(t *testing.T, th *SearchTestHelper) { - p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "email test@test.com", "", model.PostTypeDefault, 0, false) - require.NoError(t, err) - _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "email test2@test.com", "", model.PostTypeDefault, 0, false) - require.NoError(t, err) - defer th.deleteUserPosts(th.User.Id) - - params := &model.SearchParams{Terms: "\"test@test.com\""} - results, err := th.Store.Post().SearchPostsForUser(th.Context, []*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) - require.NoError(t, err) - - require.Len(t, results.Posts, 1) - th.checkPostInSearchResults(t, p1.Id, results.Posts) -} - func testSearchMarkdownUnderscores(t *testing.T, th *SearchTestHelper) { p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "_start middle end_ _another_", "", model.PostTypeDefault, 0, false) require.NoError(t, err) diff --git a/server/channels/store/sqlstore/access_control_policy_store.go b/server/channels/store/sqlstore/access_control_policy_store.go index 06121074c80..fa52eddf973 100644 --- a/server/channels/store/sqlstore/access_control_policy_store.go +++ b/server/channels/store/sqlstore/access_control_policy_store.go @@ -359,12 +359,7 @@ func (s *SqlAccessControlPolicyStore) SetActiveStatus(rctx request.CTX, id strin if existingPolicy.Type == model.AccessControlPolicyTypeParent { // if the policy is a parent, we need to update the child policies - var expr sq.Sqlizer - if s.DriverName() == model.DatabaseDriverPostgres { - expr = sq.Expr("Data->'imports' @> ?::jsonb", fmt.Sprintf("%q", id)) - } else { - expr = sq.Expr("JSON_CONTAINS(JSON_EXTRACT(Data, '$.imports'), ?)", fmt.Sprintf("%q", id)) - } + expr := sq.Expr("Data->'imports' @> ?::jsonb", fmt.Sprintf("%q", id)) query, args, err = s.getQueryBuilder().Update("AccessControlPolicies").Set("Active", active).Where(expr).ToSql() if err != nil { return nil, errors.Wrapf(err, "failed to build query for policy with id=%s", id) @@ -541,11 +536,7 @@ func (s *SqlAccessControlPolicyStore) GetAll(_ request.CTX, opts model.GetAccess query := s.selectQueryBuilder if opts.ParentID != "" { - if s.DriverName() == model.DatabaseDriverPostgres { - query = query.Where(sq.Expr("Data->'imports' @> ?", fmt.Sprintf("%q", opts.ParentID))) - } else { - query = query.Where(sq.Expr("JSON_CONTAINS(JSON_EXTRACT(Data, '$.imports'), ?)", fmt.Sprintf("%q", opts.ParentID))) - } + query = query.Where(sq.Expr("Data->'imports' @> ?", fmt.Sprintf("%q", opts.ParentID))) } if opts.Type != "" { diff --git a/server/channels/store/sqlstore/attributes_store.go b/server/channels/store/sqlstore/attributes_store.go index 466d4a52a86..f73007517e6 100644 --- a/server/channels/store/sqlstore/attributes_store.go +++ b/server/channels/store/sqlstore/attributes_store.go @@ -51,10 +51,8 @@ func newSqlAttributesStore(sqlStore *SqlStore, metrics einterfaces.MetricsInterf } func (s *SqlAttributesStore) RefreshAttributes() error { - if s.DriverName() == model.DatabaseDriverPostgres { - if _, err := s.GetMaster().Exec("REFRESH MATERIALIZED VIEW AttributeView"); err != nil { - return errors.Wrap(err, "error refreshing materialized view AttributeView") - } + if _, err := s.GetMaster().Exec("REFRESH MATERIALIZED VIEW AttributeView"); err != nil { + return errors.Wrap(err, "error refreshing materialized view AttributeView") } return nil @@ -143,8 +141,8 @@ func (s *SqlAttributesStore) SearchUsers(rctx request.CTX, opts model.SubjectSea } if term := opts.Term; strings.TrimSpace(term) != "" { - _, query = generateSearchQueryForExpression(query, strings.Fields(term), searchFields, s.DriverName() == model.DatabaseDriverPostgres, argCount) - _, count = generateSearchQueryForExpression(count, strings.Fields(term), searchFields, s.DriverName() == model.DatabaseDriverPostgres, argCount) + _, query = generateSearchQueryForExpression(query, strings.Fields(term), searchFields, argCount) + _, count = generateSearchQueryForExpression(count, strings.Fields(term), searchFields, argCount) } q, args, err := query.ToSql() @@ -211,25 +209,17 @@ func (s *SqlAttributesStore) GetChannelMembersToRemove(rctx request.CTX, channel return members, nil } -func generateSearchQueryForExpression(query sq.SelectBuilder, terms []string, fields []string, isPostgreSQL bool, prevArgs int) (int, sq.SelectBuilder) { +func generateSearchQueryForExpression(query sq.SelectBuilder, terms []string, fields []string, prevArgs int) (int, sq.SelectBuilder) { for _, term := range terms { searchFields := []string{} termArgs := []any{} for _, field := range fields { - if isPostgreSQL { - prevArgs++ - searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower($%d) escape '*' ", field, prevArgs)) - } else { - searchFields = append(searchFields, fmt.Sprintf("%s LIKE ? escape '*' ", field)) - } - termArgs = append(termArgs, fmt.Sprintf("%%%s%%", strings.TrimLeft(term, "@"))) - } - if isPostgreSQL { prevArgs++ - searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower($%d) escape '*' ", "Id", prevArgs)) - } else { - searchFields = append(searchFields, "Id = ?") + searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower($%d) escape '*' ", field, prevArgs)) + termArgs = append(termArgs, fmt.Sprintf("%%%s%%", strings.TrimLeft(term, "@"))) } + prevArgs++ + searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower($%d) escape '*' ", "Id", prevArgs)) termArgs = append(termArgs, strings.TrimLeft(term, "@")) query = query.Where(fmt.Sprintf("(%s)", strings.Join(searchFields, " OR ")), termArgs...) } diff --git a/server/channels/store/sqlstore/channel_member_history_store.go b/server/channels/store/sqlstore/channel_member_history_store.go index 89a7e5cff16..7665297c379 100644 --- a/server/channels/store/sqlstore/channel_member_history_store.go +++ b/server/channels/store/sqlstore/channel_member_history_store.go @@ -248,16 +248,12 @@ func (s SqlChannelMemberHistoryStore) PermanentDeleteBatchForRetentionPolicies(r // DeleteOrphanedRows removes entries from ChannelMemberHistory when a corresponding channel no longer exists. func (s SqlChannelMemberHistoryStore) DeleteOrphanedRows(limit int) (deleted int64, err error) { - // TODO: https://mattermost.atlassian.net/browse/MM-63368 - // We need the extra level of nesting to deal with MySQL's locking const query = ` - DELETE FROM ChannelMemberHistory WHERE (ChannelId, UserId, JoinTime) IN ( - SELECT ChannelId, UserId, JoinTime FROM ( - SELECT ChannelId, UserId, JoinTime FROM ChannelMemberHistory - LEFT JOIN Channels ON ChannelMemberHistory.ChannelId = Channels.Id - WHERE Channels.Id IS NULL - LIMIT ? - ) AS A + DELETE FROM ChannelMemberHistory WHERE ctid IN ( + SELECT ChannelMemberHistory.ctid FROM ChannelMemberHistory + LEFT JOIN Channels ON ChannelMemberHistory.ChannelId = Channels.Id + WHERE Channels.Id IS NULL + LIMIT $1 )` result, err := s.GetMaster().Exec(query, limit) if err != nil { @@ -268,39 +264,22 @@ func (s SqlChannelMemberHistoryStore) DeleteOrphanedRows(limit int) (deleted int } func (s SqlChannelMemberHistoryStore) PermanentDeleteBatch(endTime int64, limit int64) (int64, error) { - var ( - query string - args []any - err error - ) - - if s.DriverName() == model.DatabaseDriverPostgres { - var innerSelect string - innerSelect, args, err = s.getQueryBuilder(). - Select("ctid"). - From("ChannelMemberHistory"). - Where(sq.And{ - sq.NotEq{"LeaveTime": nil}, - sq.LtOrEq{"LeaveTime": endTime}, - }).Limit(uint64(limit)). - ToSql() - if err != nil { - return 0, errors.Wrap(err, "channel_member_history_to_sql") - } - query, _, err = s.getQueryBuilder(). - Delete("ChannelMemberHistory"). - Where(fmt.Sprintf( - "ctid IN (%s)", innerSelect, - )).ToSql() - } else { - query, args, err = s.getQueryBuilder(). - Delete("ChannelMemberHistory"). - Where(sq.And{ - sq.NotEq{"LeaveTime": nil}, - sq.LtOrEq{"LeaveTime": endTime}, - }). - Limit(uint64(limit)).ToSql() + innerSelect, args, err := s.getQueryBuilder(). + Select("ctid"). + From("ChannelMemberHistory"). + Where(sq.And{ + sq.NotEq{"LeaveTime": nil}, + sq.LtOrEq{"LeaveTime": endTime}, + }).Limit(uint64(limit)). + ToSql() + if err != nil { + return 0, errors.Wrap(err, "channel_member_history_to_sql") } + query, _, err := s.getQueryBuilder(). + Delete("ChannelMemberHistory"). + Where(fmt.Sprintf( + "ctid IN (%s)", innerSelect, + )).ToSql() if err != nil { return 0, errors.Wrap(err, "channel_member_history_to_sql") } diff --git a/server/channels/store/sqlstore/channel_store.go b/server/channels/store/sqlstore/channel_store.go index 9838763d529..0883ba73fbe 100644 --- a/server/channels/store/sqlstore/channel_store.go +++ b/server/channels/store/sqlstore/channel_store.go @@ -2531,51 +2531,44 @@ func (s SqlChannelStore) PermanentDeleteMembersByUser(rctx request.CTX, userId s func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string) (map[string]int64, error) { lastPostAtTimes := []struct { - Id string - LastPostAt int64 - TotalMsgCount int64 - TotalMsgCountRoot int64 + Id string + LastPostAt int64 }{} if len(channelIds) == 0 { return map[string]int64{}, nil } - // We use the question placeholder format for both databases, because - // we replace that with the dollar format later on. - // It's needed to support the prefix CTE query. See: https://github.com/Masterminds/squirrel/issues/285. + // We use the question placeholder format because we replace it with the + // dollar format later on. It's needed to support the prefix CTE query. + // See: https://github.com/Masterminds/squirrel/issues/285. query := sq.StatementBuilder.PlaceholderFormat(sq.Question). Select("Id, LastPostAt, TotalMsgCount, TotalMsgCountRoot"). From("Channels"). Where(sq.Eq{"Id": channelIds}) - // TODO: use a CTE for mysql too when version 8 becomes the minimum supported version. - if s.DriverName() == model.DatabaseDriverPostgres { - with := query.Prefix("WITH c AS (").Suffix(") ,") - update := sq.StatementBuilder.PlaceholderFormat(sq.Question). - Update("ChannelMembers cm"). - Set("MentionCount", 0). - Set("MentionCountRoot", 0). - Set("UrgentMentionCount", 0). - Set("MsgCount", sq.Expr("greatest(cm.MsgCount, c.TotalMsgCount)")). - Set("MsgCountRoot", sq.Expr("greatest(cm.MsgCountRoot, c.TotalMsgCountRoot)")). - Set("LastViewedAt", sq.Expr("greatest(cm.LastViewedAt, c.LastPostAt)")). - Set("LastUpdateAt", sq.Expr("greatest(cm.LastViewedAt, c.LastPostAt)")). - SuffixExpr(sq.Expr("FROM c WHERE cm.UserId = ? AND c.Id = cm.ChannelId", userId)) - updateWrap := update.Prefix("updated AS (").Suffix(")") - query = with.SuffixExpr(updateWrap).Suffix("SELECT Id, LastPostAt FROM c") - } + with := query.Prefix("WITH c AS (").Suffix(") ,") + update := sq.StatementBuilder.PlaceholderFormat(sq.Question). + Update("ChannelMembers cm"). + Set("MentionCount", 0). + Set("MentionCountRoot", 0). + Set("UrgentMentionCount", 0). + Set("MsgCount", sq.Expr("greatest(cm.MsgCount, c.TotalMsgCount)")). + Set("MsgCountRoot", sq.Expr("greatest(cm.MsgCountRoot, c.TotalMsgCountRoot)")). + Set("LastViewedAt", sq.Expr("greatest(cm.LastViewedAt, c.LastPostAt)")). + Set("LastUpdateAt", sq.Expr("greatest(cm.LastViewedAt, c.LastPostAt)")). + SuffixExpr(sq.Expr("FROM c WHERE cm.UserId = ? AND c.Id = cm.ChannelId", userId)) + updateWrap := update.Prefix("updated AS (").Suffix(")") + query = with.SuffixExpr(updateWrap).Suffix("SELECT Id, LastPostAt FROM c") sql, args, err := query.ToSql() if err != nil { return nil, errors.Wrap(err, "UpdateLastViewedAt_CTE_Tosql") } - if s.DriverName() == model.DatabaseDriverPostgres { - sql, err = sq.Dollar.ReplacePlaceholders(sql) - if err != nil { - return nil, errors.Wrap(err, "UpdateLastViewedAt_ReplacePlaceholders") - } + sql, err = sq.Dollar.ReplacePlaceholders(sql) + if err != nil { + return nil, errors.Wrap(err, "UpdateLastViewedAt_ReplacePlaceholders") } err = s.GetMaster().Select(&lastPostAtTimes, sql, args...) @@ -2588,53 +2581,9 @@ func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string) } times := map[string]int64{} - if s.DriverName() == model.DatabaseDriverPostgres { - for _, t := range lastPostAtTimes { - times[t.Id] = t.LastPostAt - } - return times, nil - } - - msgCountQuery, msgCountQueryRoot, lastViewedQuery := sq.Case("ChannelId"), sq.Case("ChannelId"), sq.Case("ChannelId") - for _, t := range lastPostAtTimes { times[t.Id] = t.LastPostAt - - msgCountQuery = msgCountQuery.When( - sq.Expr("?", t.Id), - sq.Expr("GREATEST(MsgCount, ?)", t.TotalMsgCount)) - - msgCountQueryRoot = msgCountQueryRoot.When( - sq.Expr("?", t.Id), - sq.Expr("GREATEST(MsgCountRoot, ?)", t.TotalMsgCountRoot)) - - lastViewedQuery = lastViewedQuery.When( - sq.Expr("?", t.Id), - sq.Expr("GREATEST(LastViewedAt, ?)", t.LastPostAt)) } - - updateQuery := s.getQueryBuilder().Update("ChannelMembers"). - Set("MentionCount", 0). - Set("MentionCountRoot", 0). - Set("UrgentMentionCount", 0). - Set("MsgCount", msgCountQuery). - Set("MsgCountRoot", msgCountQueryRoot). - Set("LastViewedAt", lastViewedQuery). - Set("LastUpdateAt", sq.Expr("LastViewedAt")). - Where(sq.Eq{ - "UserId": userId, - "ChannelId": channelIds, - }) - - sql, args, err = updateQuery.ToSql() - if err != nil { - return nil, errors.Wrap(err, "UpdateLastViewedAt_Update_Tosql") - } - - if _, err := s.GetMaster().Exec(sql, args...); err != nil { - return nil, errors.Wrapf(err, "failed to update ChannelMembers with userId=%s and channelId in %v", userId, channelIds) - } - return times, nil } @@ -3199,7 +3148,7 @@ func (s SqlChannelStore) AutocompleteInTeamForSearch(teamID string, userID strin } } else { // build the full text search clause - full := s.buildFulltextClauseX(term, "Name", "DisplayName", "Purpose") + full := s.buildFulltextClause(term, "Name", "DisplayName", "Purpose") // build the LIKE query likeSQL, likeArgs, err := query.Where(like).ToSql() if err != nil { @@ -3218,15 +3167,11 @@ func (s SqlChannelStore) AutocompleteInTeamForSearch(teamID string, userID strin args = append(likeArgs, fullArgs...) } - var err error - // since the UNION is not part of squirrel, we need to assemble it and then update // the placeholders manually - if s.DriverName() == model.DatabaseDriverPostgres { - sql, err = sq.Dollar.ReplacePlaceholders(sql) - if err != nil { - return nil, errors.Wrap(err, "AutocompleteInTeamForSearch_Placeholder") - } + sql, err := sq.Dollar.ReplacePlaceholders(sql) + if err != nil { + return nil, errors.Wrap(err, "AutocompleteInTeamForSearch_Placeholder") } // query the database @@ -3393,13 +3338,9 @@ func (s SqlChannelStore) channelSearchQuery(opts *store.ChannelSearchOpts) sq.Se InnerJoin("RetentionPoliciesChannels ON c.Id = RetentionPoliciesChannels.ChannelId"). Where(sq.Eq{"RetentionPoliciesChannels.PolicyId": opts.PolicyID}) } else if opts.ExcludePolicyConstrained { - if s.DriverName() == model.DatabaseDriverPostgres { - query = query. - LeftJoin("RetentionPoliciesChannels ON c.Id = RetentionPoliciesChannels.ChannelId"). - Where("RetentionPoliciesChannels.ChannelId IS NULL") - } else { - query = query.Where(sq.Expr(`c.Id NOT IN (SELECT ChannelId FROM RetentionPoliciesChannels)`)) - } + query = query. + LeftJoin("RetentionPoliciesChannels ON c.Id = RetentionPoliciesChannels.ChannelId"). + Where("RetentionPoliciesChannels.ChannelId IS NULL") } else if opts.IncludePolicyID { query = query. LeftJoin("RetentionPoliciesChannels ON c.Id = RetentionPoliciesChannels.ChannelId") @@ -3420,12 +3361,10 @@ func (s SqlChannelStore) channelSearchQuery(opts *store.ChannelSearchOpts) sq.Se likeTerms[i] = likeTerm } likeClause = strings.ReplaceAll(likeClause, ":LikeTerm", "?") - fulltextClause, fulltextTerm := s.buildFulltextClause(opts.Term, "c.Name, c.DisplayName, c.Purpose") - fulltextClause = strings.ReplaceAll(fulltextClause, ":FulltextTerm", "?") query = query.Where(sq.Or{ sq.Expr(likeClause, likeTerms...), - sq.Expr(fulltextClause, fulltextTerm), + s.buildFulltextClause(opts.Term, "c.Name", "c.DisplayName", "c.Purpose"), }) } @@ -3474,11 +3413,7 @@ func (s SqlChannelStore) channelSearchQuery(opts *store.ChannelSearchOpts) sq.Se if opts.ExcludeAccessControlPolicyEnforced { query = query.Where("c.Id NOT IN (SELECT ID From AccessControlPolicies WHERE Type = ?)", model.AccessControlPolicyTypeChannel) } else if opts.ParentAccessControlPolicyId != "" { - if s.DriverName() == model.DatabaseDriverPostgres { - query = query.Where(sq.Expr("c.Id IN (SELECT ID From AccessControlPolicies WHERE Type = ? AND Data->'imports' @> ?)", model.AccessControlPolicyTypeChannel, fmt.Sprintf("%q", opts.ParentAccessControlPolicyId))) - } else { - query = query.Where(sq.Expr("c.Id IN (SELECT ID From AccessControlPolicies WHERE Type = ? AND JSON_CONTAINS(JSON_EXTRACT(Data, '$.imports'), ?))", model.AccessControlPolicyTypeChannel, fmt.Sprintf("%q", opts.ParentAccessControlPolicyId))) - } + query = query.Where(sq.Expr("c.Id IN (SELECT ID From AccessControlPolicies WHERE Type = ? AND Data->'imports' @> ?)", model.AccessControlPolicyTypeChannel, fmt.Sprintf("%q", opts.ParentAccessControlPolicyId))) } else if opts.AccessControlPolicyEnforced { query = query.InnerJoin("AccessControlPolicies acp ON acp.ID = c.Id") } @@ -3556,11 +3491,7 @@ func (s SqlChannelStore) buildLIKEClause(term string, searchColumns string) (lik // Prepare the LIKE portion of the query. var searchFields []string for field := range strings.SplitSeq(searchColumns, ", ") { - if s.DriverName() == model.DatabaseDriverPostgres { - searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower(%s) escape '*'", field, ":LikeTerm")) - } else { - searchFields = append(searchFields, fmt.Sprintf("%s LIKE %s escape '*'", field, ":LikeTerm")) - } + searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower(%s) escape '*'", field, ":LikeTerm")) } likeClause = fmt.Sprintf("(%s)", strings.Join(searchFields, " OR ")) @@ -3582,13 +3513,8 @@ func (s SqlChannelStore) buildLIKEClauseX(term string, searchColumns ...string) var searchFields sq.Or for _, field := range searchColumns { - if s.DriverName() == model.DatabaseDriverPostgres { - expr := fmt.Sprintf("LOWER(%s) LIKE LOWER(?) ESCAPE '*'", field) - searchFields = append(searchFields, sq.Expr(expr, likeTerm)) - } else { - expr := fmt.Sprintf("%s LIKE ? ESCAPE '*'", field) - searchFields = append(searchFields, sq.Expr(expr, likeTerm)) - } + expr := fmt.Sprintf("LOWER(%s) LIKE LOWER(?) ESCAPE '*'", field) + searchFields = append(searchFields, sq.Expr(expr, likeTerm)) } return searchFields @@ -3596,71 +3522,28 @@ func (s SqlChannelStore) buildLIKEClauseX(term string, searchColumns ...string) const spaceFulltextSearchChars = "<>+-()~:*\"!@&" -func (s SqlChannelStore) buildFulltextClause(term string, searchColumns string) (fulltextClause, fulltextTerm string) { - // Copy the terms as we will need to prepare them differently for each search type. - fulltextTerm = term - +func (s SqlChannelStore) buildFulltextClause(term string, searchColumns ...string) sq.Sqlizer { // These chars must be treated as spaces in the fulltext query. - fulltextTerm = strings.Map(func(r rune) rune { + fulltextTerm := strings.Map(func(r rune) rune { if strings.ContainsRune(spaceFulltextSearchChars, r) { return ' ' } return r - }, fulltextTerm) + }, term) - // Prepare the FULLTEXT portion of the query. + // Remove all pipes | fulltextTerm = strings.ReplaceAll(fulltextTerm, "|", "") + // Split the search term and append :* to each part for prefix matching splitTerm := strings.Fields(fulltextTerm) - for i, t := range strings.Fields(fulltextTerm) { + for i, t := range splitTerm { splitTerm[i] = t + ":*" } + // Join the search terms with & for AND matching fulltextTerm = strings.Join(splitTerm, " & ") - fulltextClause = fmt.Sprintf("((to_tsvector('%[1]s', %[2]s)) @@ to_tsquery('%[1]s', :FulltextTerm))", s.pgDefaultTextSearchConfig, convertMySQLFullTextColumnsToPostgres(searchColumns)) - - return -} - -func (s SqlChannelStore) buildFulltextClauseX(term string, searchColumns ...string) sq.Sqlizer { - // Copy the terms as we will need to prepare them differently for each search type. - fulltextTerm := term - - // These chars must be treated as spaces in the fulltext query. - fulltextTerm = strings.Map(func(r rune) rune { - if strings.ContainsRune(spaceFulltextSearchChars, r) { - return ' ' - } - return r - }, fulltextTerm) - - // Prepare the FULLTEXT portion of the query. - if s.DriverName() == model.DatabaseDriverPostgres { - // remove all pipes | - fulltextTerm = strings.ReplaceAll(fulltextTerm, "|", "") - - // split the search term and append :* to each part - splitTerm := strings.Fields(fulltextTerm) - for i, t := range splitTerm { - splitTerm[i] = t + ":*" - } - - // join the search term with & - fulltextTerm = strings.Join(splitTerm, " & ") - - expr := fmt.Sprintf("((to_tsvector('%[1]s', %[2]s)) @@ to_tsquery('%[1]s', ?))", s.pgDefaultTextSearchConfig, strings.Join(searchColumns, " || ' ' || ")) - return sq.Expr(expr, fulltextTerm) - } - - splitTerm := strings.Fields(fulltextTerm) - for i, t := range splitTerm { - splitTerm[i] = "+" + t + "*" - } - - fulltextTerm = strings.Join(splitTerm, " ") - - expr := fmt.Sprintf("MATCH(%s) AGAINST (? IN BOOLEAN MODE)", strings.Join(searchColumns, ", ")) + expr := fmt.Sprintf("((to_tsvector('%[1]s', %[2]s)) @@ to_tsquery('%[1]s', ?))", s.pgDefaultTextSearchConfig, strings.Join(searchColumns, " || ' ' || ")) return sq.Expr(expr, fulltextTerm) } @@ -3685,57 +3568,19 @@ func (s SqlChannelStore) searchClause(term string) sq.Sqlizer { return nil } - fulltextClause := s.buildFulltextClauseX(term, "c.Name", "c.DisplayName", "c.Purpose") return sq.Or{ likeClause, - fulltextClause, + s.buildFulltextClause(term, "c.Name", "c.DisplayName", "c.Purpose"), } } -func (s SqlChannelStore) searchGroupChannelsQuery(userId, term string, isPostgreSQL bool) sq.SelectBuilder { - var baseLikeTerm string +func (s SqlChannelStore) searchGroupChannelsQuery(userId, term string) sq.SelectBuilder { + baseLikeTerm := "ARRAY_TO_STRING(ARRAY_AGG(u.Username), ', ') LIKE ?" terms := strings.Fields((strings.ToLower(term))) having := sq.And{} - if isPostgreSQL { - baseLikeTerm = "ARRAY_TO_STRING(ARRAY_AGG(u.Username), ', ') LIKE ?" - cc := s.getSubQueryBuilder().Select("c.Id"). - From("Channels c"). - Join("ChannelMembers cm ON c.Id=cm.ChannelId"). - Join("Users u on u.Id = cm.UserId"). - Where(sq.Eq{ - "c.Type": model.ChannelTypeGroup, - "u.id": userId, - }). - GroupBy("c.Id") - - for _, term := range terms { - term = sanitizeSearchTerm(term, "\\") - having = append(having, sq.Expr(baseLikeTerm, "%"+term+"%")) - } - - subq := s.getSubQueryBuilder().Select("cc.id"). - FromSelect(cc, "cc"). - Join("ChannelMembers cm On cc.Id = cm.ChannelId"). - Join("Users u On u.Id = cm.UserId"). - GroupBy("cc.Id"). - Having(having). - Limit(model.ChannelSearchDefaultLimit) - - return s.getQueryBuilder().Select(channelSliceColumns(true)...). - From("Channels"). - Where(sq.Expr("Id IN (?)", subq)) - } - - baseLikeTerm = "GROUP_CONCAT(u.Username SEPARATOR ', ') LIKE ?" - - for _, term := range terms { - term = sanitizeSearchTerm(term, "\\") - having = append(having, sq.Expr(baseLikeTerm, "%"+term+"%")) - } - - cc := s.getSubQueryBuilder().Select(channelSliceColumns(true, "c")...). + cc := s.getSubQueryBuilder().Select("c.Id"). From("Channels c"). Join("ChannelMembers cm ON c.Id=cm.ChannelId"). Join("Users u on u.Id = cm.UserId"). @@ -3745,18 +3590,26 @@ func (s SqlChannelStore) searchGroupChannelsQuery(userId, term string, isPostgre }). GroupBy("c.Id") - return s.getQueryBuilder().Select(channelSliceColumns(true, "cc")...). + for _, term := range terms { + term = sanitizeSearchTerm(term, "\\") + having = append(having, sq.Expr(baseLikeTerm, "%"+term+"%")) + } + + subq := s.getSubQueryBuilder().Select("cc.id"). FromSelect(cc, "cc"). - Join("ChannelMembers cm on cc.Id = cm.ChannelId"). - Join("Users u on u.Id = cm.UserId"). + Join("ChannelMembers cm On cc.Id = cm.ChannelId"). + Join("Users u On u.Id = cm.UserId"). GroupBy("cc.Id"). Having(having). Limit(model.ChannelSearchDefaultLimit) + + return s.getQueryBuilder().Select(channelSliceColumns(true)...). + From("Channels"). + Where(sq.Expr("Id IN (?)", subq)) } func (s SqlChannelStore) SearchGroupChannels(userId, term string) (model.ChannelList, error) { - isPostgreSQL := s.DriverName() == model.DatabaseDriverPostgres - query := s.searchGroupChannelsQuery(userId, term, isPostgreSQL) + query := s.searchGroupChannelsQuery(userId, term) sql, params, err := query.ToSql() if err != nil { @@ -4240,23 +4093,14 @@ func (s SqlChannelStore) UserBelongsToChannels(userId string, channelIds []strin // UpdateMembersRole updates all the members of channelID in the adminIDs string array to be admins and sets all other // users as not being admin. -// It returns the list of userIDs whose roles got updated. +// It returns the list of members whose roles got updated. // // TODO: parameterize adminIDs -func (s SqlChannelStore) UpdateMembersRole(channelID string, adminIDs []string) (_ []*model.ChannelMember, err error) { - transaction, err := s.GetMaster().Beginx() - if err != nil { - return nil, err - } - defer finalizeTransactionX(transaction, &err) - - // On MySQL it's not possible to update a table and select from it in the same query. - // A SELECT and a UPDATE query are needed. - // Once we only support PostgreSQL, this can be done in a single query using RETURNING. - query, args, err := s.getQueryBuilder(). - Select(channelMemberSliceColumns()...). - From("ChannelMembers"). - Where(sq.Eq{"ChannelID": channelID}). +func (s SqlChannelStore) UpdateMembersRole(channelID string, adminIDs []string) ([]*model.ChannelMember, error) { + query := s.getQueryBuilder(). + Update("ChannelMembers"). + Set("SchemeAdmin", sq.Case().When(sq.Eq{"UserId": adminIDs}, "true").Else("false")). + Where(sq.Eq{"ChannelId": channelID}). Where(sq.Or{sq.Eq{"SchemeGuest": false}, sq.Expr("SchemeGuest IS NULL")}). Where( sq.Or{ @@ -4271,42 +4115,14 @@ func (s SqlChannelStore) UpdateMembersRole(channelID string, adminIDs []string) sq.NotEq{"UserId": adminIDs}, }, }, - ).ToSql() - if err != nil { - return nil, errors.Wrap(err, "channel_tosql") - } + ). + Suffix("RETURNING " + strings.Join(channelMemberSliceColumns(), ", ")) var updatedMembers []*model.ChannelMember - if err = transaction.Select(&updatedMembers, query, args...); err != nil { - return nil, errors.Wrap(err, "failed to get list of updated users") - } - - // Update SchemeAdmin field as the data from the SQL is not updated yet - for _, member := range updatedMembers { - if slices.Contains(adminIDs, member.UserId) { - member.SchemeAdmin = true - } else { - member.SchemeAdmin = false - } - } - - query, args, err = s.getQueryBuilder(). - Update("ChannelMembers"). - Set("SchemeAdmin", sq.Case().When(sq.Eq{"UserId": adminIDs}, "true").Else("false")). - Where(sq.Eq{"ChannelId": channelID}). - Where(sq.Or{sq.Eq{"SchemeGuest": false}, sq.Expr("SchemeGuest IS NULL")}).ToSql() - if err != nil { - return nil, errors.Wrap(err, "team_tosql") - } - - if _, err = transaction.Exec(query, args...); err != nil { + if err := s.GetMaster().SelectBuilder(&updatedMembers, query); err != nil { return nil, errors.Wrap(err, "failed to update ChannelMembers") } - if err = transaction.Commit(); err != nil { - return nil, errors.Wrap(err, "commit_transaction") - } - return updatedMembers, nil } diff --git a/server/channels/store/sqlstore/draft_store.go b/server/channels/store/sqlstore/draft_store.go index 64c72070e49..8b7e57fe5f6 100644 --- a/server/channels/store/sqlstore/draft_store.go +++ b/server/channels/store/sqlstore/draft_store.go @@ -229,22 +229,18 @@ func (s *SqlDraftStore) GetMaxDraftSize() int { func (s *SqlDraftStore) determineMaxDraftSize() int { var maxDraftSizeBytes int32 - if s.DriverName() == model.DatabaseDriverPostgres { - // The Draft.Message column in Postgres has historically been VARCHAR(4000), but - // may be manually enlarged to support longer drafts. - if err := s.GetReplica().Get(&maxDraftSizeBytes, ` - SELECT - COALESCE(character_maximum_length, 0) - FROM - information_schema.columns - WHERE - table_name = 'drafts' - AND column_name = 'message' - `); err != nil { - mlog.Warn("Unable to determine the maximum supported draft size", mlog.Err(err)) - } - } else { - mlog.Warn("No implementation found to determine the maximum supported draft size") + // The Draft.Message column has historically been VARCHAR(4000), but + // may be manually enlarged to support longer drafts. + if err := s.GetReplica().Get(&maxDraftSizeBytes, ` + SELECT + COALESCE(character_maximum_length, 0) + FROM + information_schema.columns + WHERE + table_name = 'drafts' + AND column_name = 'message' + `); err != nil { + mlog.Warn("Unable to determine the maximum supported draft size", mlog.Err(err)) } // Assume a worst-case representation of four bytes per rune. @@ -288,31 +284,28 @@ func (s *SqlDraftStore) GetLastCreateAtAndUserIdValuesForEmptyDraftsMigration(cr } func (s *SqlDraftStore) DeleteEmptyDraftsByCreateAtAndUserId(createAt int64, userId string) error { - var builder Builder - if s.DriverName() == model.DatabaseDriverPostgres { - builder = s.getQueryBuilder(). - Delete("Drafts d"). - PrefixExpr(s.getQueryBuilder().Select(). - Prefix("WITH dd AS ("). - Columns("UserId", "ChannelId", "RootId"). - From("Drafts"). - Where(sq.Or{ - sq.Gt{"CreateAt": createAt}, - sq.And{ - sq.Eq{"CreateAt": createAt}, - sq.Gt{"UserId": userId}, - }, - }). - OrderBy("CreateAt", "UserId"). - Limit(100). - Suffix(")"), - ). - Using("dd"). - Where("d.UserId = dd.UserId"). - Where("d.ChannelId = dd.ChannelId"). - Where("d.RootId = dd.RootId"). - Where("d.Message = ''") - } + builder := s.getQueryBuilder(). + Delete("Drafts d"). + PrefixExpr(s.getQueryBuilder().Select(). + Prefix("WITH dd AS ("). + Columns("UserId", "ChannelId", "RootId"). + From("Drafts"). + Where(sq.Or{ + sq.Gt{"CreateAt": createAt}, + sq.And{ + sq.Eq{"CreateAt": createAt}, + sq.Gt{"UserId": userId}, + }, + }). + OrderBy("CreateAt", "UserId"). + Limit(100). + Suffix(")"), + ). + Using("dd"). + Where("d.UserId = dd.UserId"). + Where("d.ChannelId = dd.ChannelId"). + Where("d.RootId = dd.RootId"). + Where("d.Message = ''") if _, err := s.GetMaster().ExecBuilder(builder); err != nil { return errors.Wrapf(err, "failed to delete empty drafts") @@ -322,31 +315,28 @@ func (s *SqlDraftStore) DeleteEmptyDraftsByCreateAtAndUserId(createAt int64, use } func (s *SqlDraftStore) DeleteOrphanDraftsByCreateAtAndUserId(createAt int64, userId string) error { - var builder Builder - if s.DriverName() == model.DatabaseDriverPostgres { - builder = s.getQueryBuilder(). - Delete("Drafts d"). - PrefixExpr(s.getQueryBuilder().Select(). - Prefix("WITH dd AS ("). - Columns("UserId", "ChannelId", "RootId"). - From("Drafts"). - Where(sq.Or{ - sq.Gt{"CreateAt": createAt}, - sq.And{ - sq.Eq{"CreateAt": createAt}, - sq.Gt{"UserId": userId}, - }, - }). - OrderBy("CreateAt", "UserId"). - Limit(100). - Suffix(")"), - ). - Using("dd"). - Where("d.UserId = dd.UserId"). - Where("d.ChannelId = dd.ChannelId"). - Where("d.RootId = dd.RootId"). - Suffix("AND (d.RootId IN (SELECT Id FROM Posts WHERE DeleteAt <> 0) OR NOT EXISTS (SELECT 1 FROM Posts WHERE Posts.Id = d.RootId))") - } + builder := s.getQueryBuilder(). + Delete("Drafts d"). + PrefixExpr(s.getQueryBuilder().Select(). + Prefix("WITH dd AS ("). + Columns("UserId", "ChannelId", "RootId"). + From("Drafts"). + Where(sq.Or{ + sq.Gt{"CreateAt": createAt}, + sq.And{ + sq.Eq{"CreateAt": createAt}, + sq.Gt{"UserId": userId}, + }, + }). + OrderBy("CreateAt", "UserId"). + Limit(100). + Suffix(")"), + ). + Using("dd"). + Where("d.UserId = dd.UserId"). + Where("d.ChannelId = dd.ChannelId"). + Where("d.RootId = dd.RootId"). + Suffix("AND (d.RootId IN (SELECT Id FROM Posts WHERE DeleteAt <> 0) OR NOT EXISTS (SELECT 1 FROM Posts WHERE Posts.Id = d.RootId))") if _, err := s.GetMaster().ExecBuilder(builder); err != nil { return errors.Wrapf(err, "failed to delete orphan drafts") diff --git a/server/channels/store/sqlstore/file_info_store.go b/server/channels/store/sqlstore/file_info_store.go index ed0703b7a8f..753a6b38317 100644 --- a/server/channels/store/sqlstore/file_info_store.go +++ b/server/channels/store/sqlstore/file_info_store.go @@ -417,7 +417,6 @@ func (fs SqlFileInfoStore) AttachToPost(rctx request.CTX, fileId, postId, channe count, err := sqlResult.RowsAffected() if err != nil { - // RowsAffected should never fail with the MySQL or Postgres drivers return errors.Wrap(err, "unable to retrieve rows affected") } else if count == 0 { // Could not attach the file to the post @@ -494,12 +493,7 @@ func (fs SqlFileInfoStore) PermanentDelete(rctx request.CTX, fileId string) erro } func (fs SqlFileInfoStore) PermanentDeleteBatch(rctx request.CTX, endTime int64, limit int64) (int64, error) { - var query string - if fs.DriverName() == "postgres" { - query = "DELETE from FileInfo WHERE Id = any (array (SELECT Id FROM FileInfo WHERE CreateAt < ? AND CreatorId != ? LIMIT ?))" - } else { - query = "DELETE from FileInfo WHERE CreateAt < ? AND CreatorId != ? LIMIT ?" - } + query := "DELETE from FileInfo WHERE Id = any (array (SELECT Id FROM FileInfo WHERE CreateAt < ? AND CreatorId != ? LIMIT ?))" sqlResult, err := fs.GetMaster().Exec(query, endTime, model.BookmarkFileOwner, limit) if err != nil { @@ -625,14 +619,14 @@ func (fs SqlFileInfoStore) Search(rctx request.CTX, paramsList []*model.SearchPa terms := params.Terms excludedTerms := params.ExcludedTerms - for _, c := range fs.specialSearchChars() { + for _, c := range specialSearchChars { terms = strings.Replace(terms, c, " ", -1) excludedTerms = strings.Replace(excludedTerms, c, " ", -1) } if terms == "" && excludedTerms == "" { // we've already confirmed that we have a channel or user to search for - } else if fs.DriverName() == model.DatabaseDriverPostgres { + } else { // Parse text for wildcards if wildcard, err := regexp.Compile(`\*($| )`); err == nil { terms = wildcard.ReplaceAllLiteralString(terms, ":* ") @@ -683,17 +677,9 @@ func (fs SqlFileInfoStore) Search(rctx request.CTX, paramsList []*model.SearchPa } func (fs SqlFileInfoStore) CountAll() (int64, error) { - var query sq.SelectBuilder - if fs.DriverName() == model.DatabaseDriverPostgres { - query = fs.getQueryBuilder(). - Select("num"). - From("file_stats") - } else { - query = fs.getQueryBuilder(). - Select("COUNT(*)"). - From("FileInfo"). - Where("DeleteAt = 0") - } + query := fs.getQueryBuilder(). + Select("num"). + From("file_stats") var count int64 err := fs.GetReplica().GetBuilder(&count, query) @@ -733,7 +719,7 @@ func (fs SqlFileInfoStore) GetFilesBatchForIndexing(startTime int64, startFileID func (fs SqlFileInfoStore) GetStorageUsage(_, includeDeleted bool) (int64, error) { var query sq.SelectBuilder - if fs.DriverName() == model.DatabaseDriverPostgres && !includeDeleted { + if !includeDeleted { query = fs.getQueryBuilder(). Select("usage"). From("file_stats") @@ -741,10 +727,6 @@ func (fs SqlFileInfoStore) GetStorageUsage(_, includeDeleted bool) (int64, error query = fs.getQueryBuilder(). Select("COALESCE(SUM(Size), 0)"). From("FileInfo") - - if !includeDeleted { - query = query.Where("DeleteAt = 0") - } } var size int64 @@ -812,15 +794,13 @@ func (fs SqlFileInfoStore) RestoreForPostByIds(rctx request.CTX, postId string, } func (fs SqlFileInfoStore) RefreshFileStats() error { - if fs.DriverName() == model.DatabaseDriverPostgres { - // CONCURRENTLY is not used deliberately because as per Postgres docs, - // not using CONCURRENTLY takes less resources and completes faster - // at the expense of locking the mat view. Since viewing admin console - // is not a very frequent activity, we accept the tradeoff to let the - // refresh happen as fast as possible. - if _, err := fs.GetMaster().Exec("REFRESH MATERIALIZED VIEW file_stats"); err != nil { - return errors.Wrap(err, "error refreshing materialized view file_stats") - } + // CONCURRENTLY is not used deliberately because as per Postgres docs, + // not using CONCURRENTLY takes less resources and completes faster + // at the expense of locking the mat view. Since viewing admin console + // is not a very frequent activity, we accept the tradeoff to let the + // refresh happen as fast as possible. + if _, err := fs.GetMaster().Exec("REFRESH MATERIALIZED VIEW file_stats"); err != nil { + return errors.Wrap(err, "error refreshing materialized view file_stats") } return nil diff --git a/server/channels/store/sqlstore/job_store.go b/server/channels/store/sqlstore/job_store.go index 5db507bbbc5..cb39c58d13d 100644 --- a/server/channels/store/sqlstore/job_store.go +++ b/server/channels/store/sqlstore/job_store.go @@ -434,12 +434,7 @@ func (jss SqlJobStore) Delete(id string) (string, error) { } func (jss SqlJobStore) Cleanup(expiryTime int64, batchSize int) error { - var query string - if jss.DriverName() == model.DatabaseDriverPostgres { - query = "DELETE FROM Jobs WHERE Id IN (SELECT Id FROM Jobs WHERE CreateAt < ? AND (Status != ? AND Status != ?) ORDER BY CreateAt ASC LIMIT ?)" - } else { - query = "DELETE FROM Jobs WHERE CreateAt < ? AND (Status != ? AND Status != ?) ORDER BY CreateAt ASC LIMIT ?" - } + query := "DELETE FROM Jobs WHERE Id IN (SELECT Id FROM Jobs WHERE CreateAt < ? AND (Status != ? AND Status != ?) ORDER BY CreateAt ASC LIMIT ?)" var rowsAffected int64 = 1 diff --git a/server/channels/store/sqlstore/migrate.go b/server/channels/store/sqlstore/migrate.go index aabd969ef7b..9a474e58f0e 100644 --- a/server/channels/store/sqlstore/migrate.go +++ b/server/channels/store/sqlstore/migrate.go @@ -17,7 +17,6 @@ import ( "github.com/mattermost/mattermost/server/public/shared/mlog" "github.com/mattermost/mattermost/server/v8/channels/db" "github.com/mattermost/morph" - "github.com/mattermost/morph/drivers" ps "github.com/mattermost/morph/drivers/postgres" "github.com/mattermost/morph/models" mbindata "github.com/mattermost/morph/sources/embedded" @@ -111,13 +110,7 @@ func (ss *SqlStore) initMorph(dryRun, enableLogging bool) (*morph.Morph, error) return nil, err } - var driver drivers.Driver - switch ss.DriverName() { - case model.DatabaseDriverPostgres: - driver, err = ps.WithInstance(ss.GetMaster().DB.DB) - default: - err = fmt.Errorf("unsupported database type %s for migration", ss.DriverName()) - } + driver, err := ps.WithInstance(ss.GetMaster().DB.DB) if err != nil { return nil, err } diff --git a/server/channels/store/sqlstore/post_store.go b/server/channels/store/sqlstore/post_store.go index b79fb58eb50..984a7d3c249 100644 --- a/server/channels/store/sqlstore/post_store.go +++ b/server/channels/store/sqlstore/post_store.go @@ -1698,10 +1698,7 @@ func (s *SqlPostStore) getPostsAround(rctx request.CTX, before bool, options mod } query = query.From("Posts p"). Where(conditions). - // Adding ChannelId and DeleteAt order columns - // to let mysql choose the "idx_posts_channel_id_delete_at_create_at" index always. - // See MM-24170. - OrderBy("p.ChannelId", "p.DeleteAt", "p.CreateAt "+sort). + OrderBy("p.CreateAt " + sort). Limit(uint64(options.PerPage)). Offset(uint64(offset)) @@ -1785,10 +1782,7 @@ func (s *SqlPostStore) getPostIdAroundTime(channelId string, time int64, before Select("Id"). From("Posts"). Where(conditions). - // Adding ChannelId and DeleteAt order columns - // to let mysql choose the "idx_posts_channel_id_delete_at_create_at" index always. - // See MM-23369. - OrderBy("Posts.ChannelId", "Posts.DeleteAt", "Posts.CreateAt "+sort). + OrderBy("Posts.CreateAt " + sort). Limit(1) var postId string @@ -1812,10 +1806,7 @@ func (s *SqlPostStore) GetPostAfterTime(channelId string, time int64, collapsedT } query := s.postsQuery. Where(conditions). - // Adding ChannelId and DeleteAt order columns - // to let mysql choose the "idx_posts_channel_id_delete_at_create_at" index always. - // See MM-23369. - OrderBy("Posts.ChannelId", "Posts.DeleteAt", "Posts.CreateAt ASC"). + OrderBy("Posts.CreateAt ASC"). Limit(1) var post model.Post @@ -1853,76 +1844,6 @@ func (s *SqlPostStore) getRootPosts(channelId string, offset int, limit int, ski } func (s *SqlPostStore) getParentsPosts(channelId string, offset int, limit int, skipFetchThreads bool, includeDeleted bool) ([]*model.Post, error) { - if s.DriverName() == model.DatabaseDriverPostgres { - return s.getParentsPostsPostgreSQL(channelId, offset, limit, skipFetchThreads, includeDeleted) - } - - deleteAtCondition := "AND DeleteAt = 0" - if includeDeleted { - deleteAtCondition = "" - } - - // query parent Ids first - roots := []string{} - rootQuery := ` - SELECT DISTINCT - q.RootId - FROM - (SELECT - Posts.RootId - FROM - Posts - WHERE - ChannelId = ? ` + deleteAtCondition + ` - ORDER BY CreateAt DESC - LIMIT ? OFFSET ?) q - WHERE q.RootId != ''` - - err := s.GetReplica().Select(&roots, rootQuery, channelId, limit, offset) - if err != nil { - return nil, errors.Wrap(err, "failed to find Posts") - } - if len(roots) == 0 { - return nil, nil - } - - cols := postSliceColumnsWithName("p") - var where sq.Sqlizer - where = sq.Eq{"p.Id": roots} - if skipFetchThreads { - col := "(SELECT COUNT(*) FROM Posts WHERE Posts.RootId = (CASE WHEN p.RootId = '' THEN p.Id ELSE p.RootId END)) as ReplyCount" - if !includeDeleted { - col = "(SELECT COUNT(*) FROM Posts WHERE Posts.RootId = (CASE WHEN p.RootId = '' THEN p.Id ELSE p.RootId END) AND Posts.DeleteAt = 0) as ReplyCount" - } - cols = append(cols, col) - } else { - where = sq.Or{ - where, - sq.Eq{"p.RootId": roots}, - } - } - - query := s.getQueryBuilder(). - Select(cols...). - From("Posts p"). - Where(sq.And{ - where, - sq.Eq{"p.ChannelId": channelId}, - }). - OrderBy("p.CreateAt") - - if !includeDeleted { - query = query.Where(sq.Eq{"p.DeleteAt": 0}) - } - - posts := []*model.Post{} - if err := s.GetReplica().SelectBuilder(&posts, query); err != nil { - return nil, errors.Wrap(err, "failed to find Posts") - } - return posts, nil -} - -func (s *SqlPostStore) getParentsPostsPostgreSQL(channelId string, offset int, limit int, skipFetchThreads bool, includeDeleted bool) ([]*model.Post, error) { posts := []*model.Post{} replyCountQuery := "" onStatement := "q1.RootId = q2.Id" @@ -2159,7 +2080,7 @@ func (s *SqlPostStore) search(teamId string, userId string, params *model.Search } } - for _, c := range s.specialSearchChars() { + for _, c := range specialSearchChars { if !params.IsHashtag { terms = strings.Replace(terms, c, " ", -1) } @@ -2275,9 +2196,9 @@ func (s *SqlPostStore) search(teamId string, userId string, params *model.Search // TODO: convert to squirrel HW func (s *SqlPostStore) AnalyticsUserCountsWithPostsByDay(teamId string) (model.AnalyticsRows, error) { var args []any - query := `SELECT DISTINCT - DATE(FROM_UNIXTIME(Posts.CreateAt / 1000)) AS Name, - COUNT(DISTINCT Posts.UserId) AS Value + query := + `SELECT + TO_CHAR(DATE(TO_TIMESTAMP(Posts.CreateAt / 1000)), 'YYYY-MM-DD') AS Name, COUNT(DISTINCT Posts.UserId) AS Value FROM Posts` if teamId != "" { @@ -2288,28 +2209,10 @@ func (s *SqlPostStore) AnalyticsUserCountsWithPostsByDay(teamId string) (model.A } query += ` Posts.CreateAt >= ? AND Posts.CreateAt <= ? - GROUP BY DATE(FROM_UNIXTIME(Posts.CreateAt / 1000)) + GROUP BY DATE(TO_TIMESTAMP(Posts.CreateAt / 1000)) ORDER BY Name DESC LIMIT 30` - if s.DriverName() == model.DatabaseDriverPostgres { - query = `SELECT - TO_CHAR(DATE(TO_TIMESTAMP(Posts.CreateAt / 1000)), 'YYYY-MM-DD') AS Name, COUNT(DISTINCT Posts.UserId) AS Value - FROM Posts` - - if teamId != "" { - query += " INNER JOIN Channels ON Posts.ChannelId = Channels.Id AND Channels.TeamId = ? AND" - args = []any{teamId} - } else { - query += " WHERE" - } - - query += ` Posts.CreateAt >= ? AND Posts.CreateAt <= ? - GROUP BY DATE(TO_TIMESTAMP(Posts.CreateAt / 1000)) - ORDER BY Name DESC - LIMIT 30` - } - end := utils.MillisFromTime(utils.EndOfDay(utils.Yesterday())) start := utils.MillisFromTime(utils.StartOfDay(utils.Yesterday().AddDate(0, 0, -31))) args = append(args, start, end) @@ -2385,55 +2288,16 @@ func (s *SqlPostStore) countPostsByDay(teamID, startDay, endDay string) (model.A // TODO: convert to squirrel HW func (s *SqlPostStore) AnalyticsPostCountsByDay(options *model.AnalyticsPostCountsOptions) (model.AnalyticsRows, error) { - if s.DriverName() == model.DatabaseDriverPostgres { - endDay := utils.Yesterday().Format("2006-01-02") - startDay := utils.Yesterday().AddDate(0, 0, -31).Format("2006-01-02") - if options.YesterdayOnly { - startDay = utils.Yesterday().AddDate(0, 0, -1).Format("2006-01-02") - } - // Use materialized views - if options.BotsOnly { - return s.countBotPostsByDay(options.TeamId, startDay, endDay) - } - return s.countPostsByDay(options.TeamId, startDay, endDay) - } - - var args []any - query := `SELECT - DATE(FROM_UNIXTIME(Posts.CreateAt / 1000)) AS Name, - COUNT(Posts.Id) AS Value - FROM Posts` - - if options.BotsOnly { - query += " INNER JOIN Bots ON Posts.UserId = Bots.Userid" - } - - if options.TeamId != "" { - query += " INNER JOIN Channels ON Posts.ChannelId = Channels.Id AND Channels.TeamId = ? AND" - args = []any{options.TeamId} - } else { - query += " WHERE" - } - - query += ` Posts.CreateAt <= ? - AND Posts.CreateAt >= ? - GROUP BY DATE(FROM_UNIXTIME(Posts.CreateAt / 1000)) - ORDER BY Name DESC - LIMIT 30` - - end := utils.MillisFromTime(utils.EndOfDay(utils.Yesterday())) - start := utils.MillisFromTime(utils.StartOfDay(utils.Yesterday().AddDate(0, 0, -31))) + endDay := utils.Yesterday().Format("2006-01-02") + startDay := utils.Yesterday().AddDate(0, 0, -31).Format("2006-01-02") if options.YesterdayOnly { - start = utils.MillisFromTime(utils.StartOfDay(utils.Yesterday().AddDate(0, 0, -1))) + startDay = utils.Yesterday().AddDate(0, 0, -1).Format("2006-01-02") } - args = append(args, end, start) - - rows := model.AnalyticsRows{} - err := s.GetReplica().Select(&rows, query, args...) - if err != nil { - return nil, errors.Wrapf(err, "failed to find Posts with teamId=%s", options.TeamId) + // Use materialized views + if options.BotsOnly { + return s.countBotPostsByDay(options.TeamId, startDay, endDay) } - return rows, nil + return s.countPostsByDay(options.TeamId, startDay, endDay) } func (s *SqlPostStore) countByTeam(teamID string) (int64, error) { @@ -2455,11 +2319,7 @@ func (s *SqlPostStore) countByTeam(teamID string) (int64, error) { } func (s *SqlPostStore) AnalyticsPostCountByTeam(teamID string) (int64, error) { - if s.DriverName() == model.DatabaseDriverPostgres { - return s.countByTeam(teamID) - } - - return s.AnalyticsPostCount(&model.PostCountOptions{TeamId: teamID}) + return s.countByTeam(teamID) } func (s *SqlPostStore) AnalyticsPostCount(options *model.PostCountOptions) (int64, error) { @@ -2630,12 +2490,7 @@ func (s *SqlPostStore) PermanentDeleteBatchForRetentionPolicies(retentionPolicyB } func (s *SqlPostStore) PermanentDeleteBatch(endTime int64, limit int64) (int64, error) { - var query string - if s.DriverName() == model.DatabaseDriverPostgres { - query = "DELETE from Posts WHERE Id = any (array (SELECT Id FROM Posts WHERE CreateAt < ? LIMIT ?))" - } else { - query = "DELETE from Posts WHERE CreateAt < ? LIMIT ?" - } + query := "DELETE from Posts WHERE Id = any (array (SELECT Id FROM Posts WHERE CreateAt < ? LIMIT ?))" sqlResult, err := s.GetMaster().Exec(query, endTime, limit) if err != nil { @@ -2668,22 +2523,18 @@ func (s *SqlPostStore) GetOldest() (*model.Post, error) { func (s *SqlPostStore) determineMaxPostSize() int { var maxPostSizeBytes int32 - if s.DriverName() == model.DatabaseDriverPostgres { - // The Post.Message column in Postgres has historically been VARCHAR(4000), but - // may be manually enlarged to support longer posts. - if err := s.GetReplica().Get(&maxPostSizeBytes, ` - SELECT - COALESCE(character_maximum_length, 0) - FROM - information_schema.columns - WHERE - table_name = 'posts' - AND column_name = 'message' - `); err != nil { - mlog.Warn("Unable to determine the maximum supported post size", mlog.Err(err)) - } - } else { - mlog.Error("No implementation found to determine the maximum supported post size") + // The Post.Message column in Postgres has historically been VARCHAR(4000), but + // may be manually enlarged to support longer posts. + if err := s.GetReplica().Get(&maxPostSizeBytes, ` + SELECT + COALESCE(character_maximum_length, 0) + FROM + information_schema.columns + WHERE + table_name = 'posts' + AND column_name = 'message' + `); err != nil { + mlog.Warn("Unable to determine the maximum supported post size", mlog.Err(err)) } // Assume a worst-case representation of four bytes per rune. @@ -2994,20 +2845,13 @@ func (s *SqlPostStore) deleteThread(transaction *sqlxTxWrapper, postId string, d } func (s *SqlPostStore) deleteThreadFiles(transaction *sqlxTxWrapper, postID string, deleteAtTime int64) error { - var query sq.UpdateBuilder - if s.DriverName() == model.DatabaseDriverPostgres { - query = s.getQueryBuilder().Update("FileInfo"). - Set("DeleteAt", deleteAtTime). - From("Posts") - } else { - query = s.getQueryBuilder().Update("FileInfo", "Posts"). - Set("FileInfo.DeleteAt", deleteAtTime) - } - - query = query.Where(sq.And{ - sq.Expr("FileInfo.PostId = Posts.Id"), - sq.Eq{"Posts.RootId": postID}, - }) + query := s.getQueryBuilder().Update("FileInfo"). + Set("DeleteAt", deleteAtTime). + From("Posts"). + Where(sq.And{ + sq.Expr("FileInfo.PostId = Posts.Id"), + sq.Eq{"Posts.RootId": postID}, + }) _, err := transaction.ExecBuilder(query) if err != nil { @@ -3039,14 +2883,7 @@ func (s *SqlPostStore) updateThreadAfterReplyDeletion(transaction *sqlxTxWrapper updateQuery := s.getQueryBuilder().Update("Threads") if count == 0 { - if s.DriverName() == model.DatabaseDriverPostgres { - updateQuery = updateQuery.Set("Participants", sq.Expr("Participants - ?", userId)) - } else { - updateQuery = updateQuery. - Set("Participants", sq.Expr( - `IFNULL(JSON_REMOVE(Participants, JSON_UNQUOTE(JSON_SEARCH(Participants, 'one', ?))), Participants)`, userId, - )) - } + updateQuery = updateQuery.Set("Participants", sq.Expr("Participants - ?", userId)) } lastReplyAtSubquery := sq.Select("COALESCE(MAX(CreateAt), 0)"). @@ -3261,40 +3098,12 @@ func (s *SqlPostStore) SetPostReminder(reminder *model.PostReminder) error { return nil } -func (s *SqlPostStore) GetPostReminders(now int64) (_ []*model.PostReminder, err error) { +func (s *SqlPostStore) GetPostReminders(now int64) ([]*model.PostReminder, error) { reminders := []*model.PostReminder{} - - transaction, err := s.GetMaster().Beginx() - if err != nil { - return nil, errors.Wrap(err, "begin_transaction") - } - defer finalizeTransactionX(transaction, &err) - - err = transaction.Select(&reminders, `SELECT PostId, UserId - FROM PostReminders - WHERE TargetTime <= ?`, now) - if err != nil && err != sql.ErrNoRows { - return nil, errors.Wrap(err, "failed to get post reminders") - } - - if err == sql.ErrNoRows { - // No need to execute delete statement if there's nothing to delete. - return reminders, nil - } - - // TODO: https://mattermost.atlassian.net/browse/MM-63368 - // Postgres supports RETURNING * in a DELETE statement, but MySQL doesn't. - // So we are stuck with 2 queries. Not taking separate paths for Postgres - // and MySQL for simplicity. - _, err = transaction.Exec(`DELETE from PostReminders WHERE TargetTime <= ?`, now) + err := s.GetMaster().Select(&reminders, `DELETE FROM PostReminders WHERE TargetTime <= $1 RETURNING PostId, UserId`, now) if err != nil { - return nil, errors.Wrap(err, "failed to delete post reminders") + return nil, errors.Wrap(err, "failed to get and delete post reminders") } - - if err = transaction.Commit(); err != nil { - return nil, errors.Wrap(err, "commit_transaction") - } - return reminders, nil } @@ -3324,19 +3133,17 @@ func (s *SqlPostStore) GetPostReminderMetadata(postID string) (*store.PostRemind } func (s *SqlPostStore) RefreshPostStats() error { - if s.DriverName() == model.DatabaseDriverPostgres { - // CONCURRENTLY is not used deliberately because as per Postgres docs, - // not using CONCURRENTLY takes less resources and completes faster - // at the expense of locking the mat view. Since viewing admin console - // is not a very frequent activity, we accept the tradeoff to let the - // refresh happen as fast as possible. - if _, err := s.GetMaster().Exec("REFRESH MATERIALIZED VIEW posts_by_team_day"); err != nil { - return errors.Wrap(err, "error refreshing materialized view posts_by_team_day") - } + // CONCURRENTLY is not used deliberately because as per Postgres docs, + // not using CONCURRENTLY takes less resources and completes faster + // at the expense of locking the mat view. Since viewing admin console + // is not a very frequent activity, we accept the tradeoff to let the + // refresh happen as fast as possible. + if _, err := s.GetMaster().Exec("REFRESH MATERIALIZED VIEW posts_by_team_day"); err != nil { + return errors.Wrap(err, "error refreshing materialized view posts_by_team_day") + } - if _, err := s.GetMaster().Exec("REFRESH MATERIALIZED VIEW bot_posts_by_team_day"); err != nil { - return errors.Wrap(err, "error refreshing materialized view bot_posts_by_team_day") - } + if _, err := s.GetMaster().Exec("REFRESH MATERIALIZED VIEW bot_posts_by_team_day"); err != nil { + return errors.Wrap(err, "error refreshing materialized view bot_posts_by_team_day") } return nil diff --git a/server/channels/store/sqlstore/preference_store.go b/server/channels/store/sqlstore/preference_store.go index 68c5620013e..2f0d5dbf071 100644 --- a/server/channels/store/sqlstore/preference_store.go +++ b/server/channels/store/sqlstore/preference_store.go @@ -224,15 +224,12 @@ func (s SqlPreferenceStore) DeleteCategoryAndName(category string, name string) // DeleteOrphanedRows removes entries from Preferences (flagged post) when a // corresponding post no longer exists. func (s *SqlPreferenceStore) DeleteOrphanedRows(limit int) (deleted int64, err error) { - // We need the extra level of nesting to deal with MySQL's locking const query = ` - DELETE FROM Preferences WHERE Name IN ( - SELECT Name FROM ( - SELECT Preferences.Name FROM Preferences - LEFT JOIN Posts ON Preferences.Name = Posts.Id - WHERE Posts.Id IS NULL AND Category = ? - LIMIT ? - ) AS A + DELETE FROM Preferences WHERE ctid IN ( + SELECT Preferences.ctid FROM Preferences + LEFT JOIN Posts ON Preferences.Name = Posts.Id + WHERE Posts.Id IS NULL AND Category = $1 + LIMIT $2 )` result, err := s.GetMaster().Exec(query, model.PreferenceCategoryFlaggedPost, limit) @@ -284,12 +281,8 @@ func (s SqlPreferenceStore) CleanupFlagsBatch(limit int64) (int64, error) { // Delete preference for limit_visible_dms_gms where their value is greater than "40" or less than "1" func (s SqlPreferenceStore) DeleteInvalidVisibleDmsGms() (int64, error) { - var queryString string - var args []any - var err error - // We need to pad the value field with zeros when doing comparison's because the value is stored as a string. - // Having them the same length allows Postgres/MySQL to compare them correctly. + // Having them the same length allows Postgres to compare them correctly. whereClause := sq.And{ sq.Eq{"Category": model.PreferenceCategorySidebarSettings}, sq.Eq{"Name": model.PreferenceLimitVisibleDmsGms}, @@ -298,28 +291,17 @@ func (s SqlPreferenceStore) DeleteInvalidVisibleDmsGms() (int64, error) { sq.Lt{"SUBSTRING(CONCAT('000000000000000', Value), LENGTH(Value) + 1, 15)": "000000000000001"}, }, } - if s.DriverName() == "postgres" { - subQuery := s.getQueryBuilder(). - Select("UserId, Category, Name"). - From("Preferences"). - Where(whereClause). - Limit(100) - queryString, args, err = s.getQueryBuilder(). - Delete("Preferences"). - Where(sq.Expr("(userid, category, name) IN (?)", subQuery)). - ToSql() - if err != nil { - return int64(0), errors.Wrap(err, "could not build sql query to delete preference") - } - } else { - queryString, args, err = s.getQueryBuilder(). - Delete("Preferences"). - Where(whereClause). - Limit(100). - ToSql() - if err != nil { - return int64(0), errors.Wrap(err, "could not build sql query to delete preference") - } + subQuery := s.getQueryBuilder(). + Select("UserId, Category, Name"). + From("Preferences"). + Where(whereClause). + Limit(100) + queryString, args, err := s.getQueryBuilder(). + Delete("Preferences"). + Where(sq.Expr("(userid, category, name) IN (?)", subQuery)). + ToSql() + if err != nil { + return int64(0), errors.Wrap(err, "could not build sql query to delete preference") } result, err := s.GetMaster().Exec(queryString, args...) diff --git a/server/channels/store/sqlstore/property_field_store.go b/server/channels/store/sqlstore/property_field_store.go index 5c5eb06d606..40d19aa4c60 100644 --- a/server/channels/store/sqlstore/property_field_store.go +++ b/server/channels/store/sqlstore/property_field_store.go @@ -200,7 +200,6 @@ func (s *SqlPropertyFieldStore) Update(groupID string, fields []*model.PropertyF defer finalizeTransactionX(transaction, &err) updateTime := model.GetMillis() - isPostgres := s.DriverName() == model.DatabaseDriverPostgres nameCase := sq.Case("id") typeCase := sq.Case("id") attrsCase := sq.Case("id") @@ -217,21 +216,12 @@ func (s *SqlPropertyFieldStore) Update(groupID string, fields []*model.PropertyF ids[i] = field.ID whenID := sq.Expr("?", field.ID) - if isPostgres { - nameCase = nameCase.When(whenID, sq.Expr("?::text", field.Name)) - typeCase = typeCase.When(whenID, sq.Expr("?::property_field_type", field.Type)) - attrsCase = attrsCase.When(whenID, sq.Expr("?::jsonb", field.Attrs)) - targetIDCase = targetIDCase.When(whenID, sq.Expr("?::text", field.TargetID)) - targetTypeCase = targetTypeCase.When(whenID, sq.Expr("?::text", field.TargetType)) - deleteAtCase = deleteAtCase.When(whenID, sq.Expr("?::bigint", field.DeleteAt)) - } else { - nameCase = nameCase.When(whenID, sq.Expr("?", field.Name)) - typeCase = typeCase.When(whenID, sq.Expr("?", field.Type)) - attrsCase = attrsCase.When(whenID, sq.Expr("?", field.Attrs)) - targetIDCase = targetIDCase.When(whenID, sq.Expr("?", field.TargetID)) - targetTypeCase = targetTypeCase.When(whenID, sq.Expr("?", field.TargetType)) - deleteAtCase = deleteAtCase.When(whenID, sq.Expr("?", field.DeleteAt)) - } + nameCase = nameCase.When(whenID, sq.Expr("?::text", field.Name)) + typeCase = typeCase.When(whenID, sq.Expr("?::property_field_type", field.Type)) + attrsCase = attrsCase.When(whenID, sq.Expr("?::jsonb", field.Attrs)) + targetIDCase = targetIDCase.When(whenID, sq.Expr("?::text", field.TargetID)) + targetTypeCase = targetTypeCase.When(whenID, sq.Expr("?::text", field.TargetType)) + deleteAtCase = deleteAtCase.When(whenID, sq.Expr("?::bigint", field.DeleteAt)) } builder := s.getQueryBuilder(). diff --git a/server/channels/store/sqlstore/property_value_store.go b/server/channels/store/sqlstore/property_value_store.go index 880594a1672..d366a6a1a76 100644 --- a/server/channels/store/sqlstore/property_value_store.go +++ b/server/channels/store/sqlstore/property_value_store.go @@ -203,7 +203,6 @@ func (s *SqlPropertyValueStore) Update(groupID string, values []*model.PropertyV defer finalizeTransactionX(transaction, &err) updateTime := model.GetMillis() - isPostgres := s.DriverName() == model.DatabaseDriverPostgres valueCase := sq.Case("id") deleteAtCase := sq.Case("id") ids := make([]string, len(values)) @@ -220,13 +219,8 @@ func (s *SqlPropertyValueStore) Update(groupID string, values []*model.PropertyV valueJSON = AppendBinaryFlag(valueJSON) } - if isPostgres { - valueCase = valueCase.When(sq.Expr("?", value.ID), sq.Expr("?::jsonb", valueJSON)) - deleteAtCase = deleteAtCase.When(sq.Expr("?", value.ID), sq.Expr("?::bigint", value.DeleteAt)) - } else { - valueCase = valueCase.When(sq.Expr("?", value.ID), sq.Expr("?", valueJSON)) - deleteAtCase = deleteAtCase.When(sq.Expr("?", value.ID), sq.Expr("?", value.DeleteAt)) - } + valueCase = valueCase.When(sq.Expr("?", value.ID), sq.Expr("?::jsonb", valueJSON)) + deleteAtCase = deleteAtCase.When(sq.Expr("?", value.ID), sq.Expr("?::bigint", value.DeleteAt)) } builder := s.getQueryBuilder(). diff --git a/server/channels/store/sqlstore/reaction_store.go b/server/channels/store/sqlstore/reaction_store.go index df06f265c72..9b20a70ccbd 100644 --- a/server/channels/store/sqlstore/reaction_store.go +++ b/server/channels/store/sqlstore/reaction_store.go @@ -345,12 +345,7 @@ func (s *SqlReactionStore) DeleteOrphanedRowsByIds(r *model.RetentionIdsForDelet } func (s *SqlReactionStore) PermanentDeleteBatch(endTime int64, limit int64) (int64, error) { - var query string - if s.DriverName() == "postgres" { - query = "DELETE from Reactions WHERE CreateAt = any (array (SELECT CreateAt FROM Reactions WHERE CreateAt < ? LIMIT ?))" - } else { - query = "DELETE from Reactions WHERE CreateAt < ? LIMIT ?" - } + query := "DELETE from Reactions WHERE CreateAt = any (array (SELECT CreateAt FROM Reactions WHERE CreateAt < ? LIMIT ?))" sqlResult, err := s.GetMaster().Exec(query, endTime, limit) if err != nil { diff --git a/server/channels/store/sqlstore/retention_policy_store.go b/server/channels/store/sqlstore/retention_policy_store.go index fbd41c1494d..b46434f59ff 100644 --- a/server/channels/store/sqlstore/retention_policy_store.go +++ b/server/channels/store/sqlstore/retention_policy_store.go @@ -5,7 +5,6 @@ package sqlstore import ( "database/sql" - "encoding/json" "fmt" "strconv" "strings" @@ -31,8 +30,7 @@ func newSqlRetentionPolicyStore(sqlStore *SqlStore, metrics einterfaces.MetricsI } } -// executePossiblyEmptyQuery only executes the query if it is non-empty. This helps avoid -// having to check for MySQL, which, unlike Postgres, does not allow empty queries. +// executePossiblyEmptyQuery only executes the query if it is non-empty. func executePossiblyEmptyQuery(txn *sqlxTxWrapper, query string, args ...any) (sql.Result, error) { if query == "" { return nil, nil @@ -641,15 +639,11 @@ func subQueryIN(property string, query sq.SelectBuilder) sq.Sqlizer { // DeleteOrphanedRows removes entries from RetentionPoliciesChannels and RetentionPoliciesTeams // where a channel or team no longer exists. func (s *SqlRetentionPolicyStore) DeleteOrphanedRows(limit int) (deleted int64, err error) { - // We need the extra level of nesting to deal with MySQL's locking - rpcSubQuery := sq.Select("ChannelId").FromSelect( - sq.Select("ChannelId"). - From("RetentionPoliciesChannels"). - LeftJoin("Channels ON RetentionPoliciesChannels.ChannelId = Channels.Id"). - Where("Channels.Id IS NULL"). - Limit(uint64(limit)), - "A", - ) + rpcSubQuery := sq.Select("ChannelId"). + From("RetentionPoliciesChannels"). + LeftJoin("Channels ON RetentionPoliciesChannels.ChannelId = Channels.Id"). + Where("Channels.Id IS NULL"). + Limit(uint64(limit)) rpcDeleteQuery, rpcArgs, err := s.getQueryBuilder(). Delete("RetentionPoliciesChannels"). @@ -659,15 +653,11 @@ func (s *SqlRetentionPolicyStore) DeleteOrphanedRows(limit int) (deleted int64, return int64(0), errors.Wrap(err, "retention_policies_channels_tosql") } - // We need the extra level of nesting to deal with MySQL's locking - rptSubQuery := sq.Select("TeamId").FromSelect( - sq.Select("TeamId"). - From("RetentionPoliciesTeams"). - LeftJoin("Teams ON RetentionPoliciesTeams.TeamId = Teams.Id"). - Where("Teams.Id IS NULL"). - Limit(uint64(limit)), - "A", - ) + rptSubQuery := sq.Select("TeamId"). + From("RetentionPoliciesTeams"). + LeftJoin("Teams ON RetentionPoliciesTeams.TeamId = Teams.Id"). + Where("Teams.Id IS NULL"). + Limit(uint64(limit)) rptDeleteQuery, rptArgs, err := s.getQueryBuilder(). Delete("RetentionPoliciesTeams"). @@ -817,26 +807,14 @@ func (s *SqlRetentionPolicyStore) GetChannelPoliciesCountForUser(userID string) return count, nil } -func scanRetentionIdsForDeletion(rows *sql.Rows, isPostgres bool) ([]*model.RetentionIdsForDeletion, error) { +func scanRetentionIdsForDeletion(rows *sql.Rows) ([]*model.RetentionIdsForDeletion, error) { idsForDeletion := []*model.RetentionIdsForDeletion{} for rows.Next() { var row model.RetentionIdsForDeletion - if isPostgres { - if err := rows.Scan( - &row.Id, &row.TableName, pq.Array(&row.Ids), - ); err != nil { - return nil, errors.Wrap(err, "unable to scan columns") - } - } else { - var ids []byte - if err := rows.Scan( - &row.Id, &row.TableName, &ids, - ); err != nil { - return nil, errors.Wrap(err, "unable to scan columns") - } - if err := json.Unmarshal(ids, &row.Ids); err != nil { - return nil, errors.Wrap(err, "failed to unmarshal ids") - } + if err := rows.Scan( + &row.Id, &row.TableName, pq.Array(&row.Ids), + ); err != nil { + return nil, errors.Wrap(err, "unable to scan columns") } idsForDeletion = append(idsForDeletion, &row) @@ -867,8 +845,7 @@ func (s *SqlRetentionPolicyStore) GetIdsForDeletionByTableName(tableName string, } defer rows.Close() - isPostgres := s.DriverName() == model.DatabaseDriverPostgres - idsForDeletion, err := scanRetentionIdsForDeletion(rows, isPostgres) + idsForDeletion, err := scanRetentionIdsForDeletion(rows) if err != nil { return nil, errors.Wrap(err, "failed to scan ids for deletion") } @@ -880,18 +857,8 @@ func insertRetentionIdsForDeletion(txn *sqlxTxWrapper, row *model.RetentionIdsFo row.PreSave() insertBuilder := s.getQueryBuilder(). Insert("RetentionIdsForDeletion"). - Columns("Id", "TableName", "Ids") - if s.DriverName() == model.DatabaseDriverPostgres { - insertBuilder = insertBuilder. - Values(row.Id, row.TableName, pq.Array(row.Ids)) - } else { - jsonIds, err := json.Marshal(row.Ids) - if err != nil { - return err - } - insertBuilder = insertBuilder. - Values(row.Id, row.TableName, jsonIds) - } + Columns("Id", "TableName", "Ids"). + Values(row.Id, row.TableName, pq.Array(row.Ids)) insertQuery, insertArgs, err := insertBuilder.ToSql() if err != nil { return err diff --git a/server/channels/store/sqlstore/schema_dump.go b/server/channels/store/sqlstore/schema_dump.go index 229d8bf7e7e..3e1a06664f0 100644 --- a/server/channels/store/sqlstore/schema_dump.go +++ b/server/channels/store/sqlstore/schema_dump.go @@ -15,12 +15,7 @@ import ( ) // GetSchemaDefinition dumps the database schema. -// Only Postgres is supported. func (ss *SqlStore) GetSchemaDefinition() (*model.SupportPacketDatabaseSchema, error) { - if ss.DriverName() != model.DatabaseDriverPostgres { - return nil, errors.New("schema dump is only supported for Postgres") - } - var schemaInfo model.SupportPacketDatabaseSchema var rErr *multierror.Error diff --git a/server/channels/store/sqlstore/session_store.go b/server/channels/store/sqlstore/session_store.go index 8b23d9d3a85..98e0e280d39 100644 --- a/server/channels/store/sqlstore/session_store.go +++ b/server/channels/store/sqlstore/session_store.go @@ -369,12 +369,7 @@ func (me SqlSessionStore) AnalyticsSessionCount() (int64, error) { } func (me SqlSessionStore) Cleanup(expiryTime int64, batchSize int64) error { - var query string - if me.DriverName() == model.DatabaseDriverPostgres { - query = "DELETE FROM Sessions WHERE Id IN (SELECT Id FROM Sessions WHERE ExpiresAt != 0 AND ? > ExpiresAt LIMIT ?)" - } else { - query = "DELETE FROM Sessions WHERE ExpiresAt != 0 AND ? > ExpiresAt LIMIT ?" - } + query := "DELETE FROM Sessions WHERE Id IN (SELECT Id FROM Sessions WHERE ExpiresAt != 0 AND ? > ExpiresAt LIMIT ?)" var rowsAffected int64 = 1 diff --git a/server/channels/store/sqlstore/shared_channel_store.go b/server/channels/store/sqlstore/shared_channel_store.go index 2a4f722fb1d..69ec6a196d2 100644 --- a/server/channels/store/sqlstore/shared_channel_store.go +++ b/server/channels/store/sqlstore/shared_channel_store.go @@ -4,7 +4,6 @@ package sqlstore import ( - "context" "database/sql" "fmt" "strings" @@ -825,30 +824,25 @@ func (s SqlSharedChannelStore) GetUsersForSync(filter model.GetUsersForSyncFilte // UpdateUserLastSyncAt updates the LastSyncAt timestamp for the specified SharedChannelUser. func (s SqlSharedChannelStore) UpdateUserLastSyncAt(userID string, channelID string, remoteID string) error { - // fetching the user first creates a minor race condition. This is mitigated by ensuring that the - // LastUpdateAt is only ever increased. Doing it this way avoids the update with join that has differing - // syntax between MySQL and Postgres which Squirrel cannot handle. It also allows us to return - // a proper error when trying to update for a non-existent user, which cannot be done by checking RowsAffected - // when doing updates; RowsAffected=0 when the LastUpdateAt doesn't change and is the same result if user doesn't - // exist. - user, err := s.stores.user.Get(context.Background(), userID) - if err != nil { - return err - } - - updateAt := max(user.UpdateAt, user.LastPictureUpdate) - + // Use UPDATE FROM with RETURNING to do this in a single query. The RETURNING clause lets us detect + // if the user doesn't exist (no rows returned). query := s.getQueryBuilder(). Update("SharedChannelUsers AS scu"). - Set("LastSyncAt", sq.Expr("GREATEST(scu.LastSyncAt, ?)", updateAt)). + Set("LastSyncAt", sq.Expr("GREATEST(scu.LastSyncAt, GREATEST(u.UpdateAt, u.LastPictureUpdate))")). + From("Users AS u"). + Where("u.Id = scu.UserId"). Where(sq.Eq{ "scu.UserId": userID, "scu.ChannelId": channelID, "scu.RemoteId": remoteID, - }) + }). + Suffix("RETURNING scu.UserId") - _, err = s.GetMaster().ExecBuilder(query) - if err != nil { + var returnedID string + if err := s.GetMaster().GetBuilder(&returnedID, query); err != nil { + if err == sql.ErrNoRows { + return store.NewErrNotFound("User", userID) + } return fmt.Errorf("failed to update LastSyncAt for SharedChannelUser with userId=%s, channelId=%s, remoteId=%s: %w", userID, channelID, remoteID, err) } diff --git a/server/channels/store/sqlstore/sqlx_wrapper.go b/server/channels/store/sqlstore/sqlx_wrapper.go index 7a9a4610858..6add61b8cc5 100644 --- a/server/channels/store/sqlstore/sqlx_wrapper.go +++ b/server/channels/store/sqlstore/sqlx_wrapper.go @@ -17,7 +17,6 @@ import ( "github.com/jmoiron/sqlx" - "github.com/mattermost/mattermost/server/public/model" "github.com/mattermost/mattermost/server/public/shared/mlog" "github.com/mattermost/mattermost/server/v8/channels/store/storetest" sq "github.com/mattermost/squirrel" @@ -63,9 +62,7 @@ type sqlxExecutor interface { SelectBuilder(dest any, builder Builder) error } -// namedParamRegex is used to capture all named parameters and convert them -// to lowercase. This is necessary to be able to use a single query for both -// Postgres and MySQL. +// namedParamRegex is used to capture all named parameters and convert them to lowercase. // This will also lowercase any constant strings containing a :, but sqlx // will fail the query, so it won't be checked in inadvertently. var namedParamRegex = regexp.MustCompile(`:\w+`) @@ -134,9 +131,7 @@ func (w *sqlxDBWrapper) GetBuilder(dest any, builder Builder) error { } func (w *sqlxDBWrapper) NamedExec(query string, arg any) (sql.Result, error) { - if w.DB.DriverName() == model.DatabaseDriverPostgres { - query = namedParamRegex.ReplaceAllStringFunc(query, strings.ToLower) - } + query = namedParamRegex.ReplaceAllStringFunc(query, strings.ToLower) ctx, cancel := context.WithTimeout(context.Background(), w.queryTimeout) defer cancel() @@ -192,9 +187,7 @@ func (w *sqlxDBWrapper) ExecRaw(query string, args ...any) (sql.Result, error) { } func (w *sqlxDBWrapper) NamedQuery(query string, arg any) (*sqlx.Rows, error) { - if w.DB.DriverName() == model.DatabaseDriverPostgres { - query = namedParamRegex.ReplaceAllStringFunc(query, strings.ToLower) - } + query = namedParamRegex.ReplaceAllStringFunc(query, strings.ToLower) ctx, cancel := context.WithTimeout(context.Background(), w.queryTimeout) defer cancel() @@ -348,9 +341,7 @@ func (w *sqlxTxWrapper) ExecRaw(query string, args ...any) (sql.Result, error) { } func (w *sqlxTxWrapper) NamedExec(query string, arg any) (sql.Result, error) { - if w.Tx.DriverName() == model.DatabaseDriverPostgres { - query = namedParamRegex.ReplaceAllStringFunc(query, strings.ToLower) - } + query = namedParamRegex.ReplaceAllStringFunc(query, strings.ToLower) ctx, cancel := context.WithTimeout(context.Background(), w.queryTimeout) defer cancel() @@ -364,9 +355,7 @@ func (w *sqlxTxWrapper) NamedExec(query string, arg any) (sql.Result, error) { } func (w *sqlxTxWrapper) NamedQuery(query string, arg any) (*sqlx.Rows, error) { - if w.Tx.DriverName() == model.DatabaseDriverPostgres { - query = namedParamRegex.ReplaceAllStringFunc(query, strings.ToLower) - } + query = namedParamRegex.ReplaceAllStringFunc(query, strings.ToLower) ctx, cancel := context.WithTimeout(context.Background(), w.queryTimeout) defer cancel() diff --git a/server/channels/store/sqlstore/status_store.go b/server/channels/store/sqlstore/status_store.go index da4f0fb5812..1ab78794dc2 100644 --- a/server/channels/store/sqlstore/status_store.go +++ b/server/channels/store/sqlstore/status_store.go @@ -26,12 +26,11 @@ func newSqlStatusStore(sqlStore *SqlStore) store.StatusStore { SqlStore: sqlStore, } - manualColumnName := quoteColumnName(s.DriverName(), "Manual") s.statusSelectQuery = s.getQueryBuilder(). Select( "COALESCE(UserId, '') AS UserId", "COALESCE(Status, '') AS Status", - fmt.Sprintf("COALESCE(%s, FALSE) AS %s", manualColumnName, manualColumnName), + "COALESCE(Manual, FALSE) AS Manual", "COALESCE(LastActivityAt, 0) AS LastActivityAt", "COALESCE(DNDEndTime, 0) AS DNDEndTime", "COALESCE(PrevStatus, '') AS PrevStatus", @@ -44,7 +43,7 @@ func newSqlStatusStore(sqlStore *SqlStore) store.StatusStore { func (s SqlStatusStore) SaveOrUpdate(st *model.Status) error { query := s.getQueryBuilder(). Insert("Status"). - Columns("UserId", "Status", quoteColumnName(s.DriverName(), "Manual"), "LastActivityAt", "DNDEndTime", "PrevStatus"). + Columns("UserId", "Status", "Manual", "LastActivityAt", "DNDEndTime", "PrevStatus"). Values(st.UserId, st.Status, st.Manual, st.LastActivityAt, st.DNDEndTime, st.PrevStatus) query = query.SuffixExpr(sq.Expr("ON CONFLICT (userid) DO UPDATE SET Status = EXCLUDED.Status, Manual = EXCLUDED.Manual, LastActivityAt = EXCLUDED.LastActivityAt, DNDEndTime = EXCLUDED.DNDEndTime, PrevStatus = EXCLUDED.PrevStatus")) @@ -70,7 +69,7 @@ func (s SqlStatusStore) SaveOrUpdateMany(statuses map[string]*model.Status) erro query := s.getQueryBuilder(). Insert("Status"). - Columns("UserId", "Status", quoteColumnName(s.DriverName(), "Manual"), "LastActivityAt", "DNDEndTime", "PrevStatus") + Columns("UserId", "Status", "Manual", "LastActivityAt", "DNDEndTime", "PrevStatus") // Add values for each unique status for _, st := range statuses { @@ -125,7 +124,7 @@ func (s SqlStatusStore) UpdateExpiredDNDStatuses() (_ []*model.Status, err error Set("Status", sq.Expr("PrevStatus")). Set("PrevStatus", model.StatusDnd). Set("DNDEndTime", 0). - Set(quoteColumnName(s.DriverName(), "Manual"), false). + Set("Manual", false). Suffix("RETURNING *") statuses := []*model.Status{} @@ -138,7 +137,7 @@ func (s SqlStatusStore) UpdateExpiredDNDStatuses() (_ []*model.Status, err error } func (s SqlStatusStore) ResetAll() error { - if _, err := s.GetMaster().Exec(fmt.Sprintf("UPDATE Status SET Status = ? WHERE %s = false", quoteColumnName(s.DriverName(), "Manual")), model.StatusOffline); err != nil { + if _, err := s.GetMaster().Exec("UPDATE Status SET Status = ? WHERE Manual = false", model.StatusOffline); err != nil { return errors.Wrap(err, "failed to update Statuses") } return nil diff --git a/server/channels/store/sqlstore/store.go b/server/channels/store/sqlstore/store.go index 4d877cb384e..79214f973a0 100644 --- a/server/channels/store/sqlstore/store.go +++ b/server/channels/store/sqlstore/store.go @@ -345,42 +345,23 @@ func (ss *SqlStore) DriverName() string { } // specialSearchChars have special meaning and can be treated as spaces -func (ss *SqlStore) specialSearchChars() []string { - chars := []string{ - "<", - ">", - "+", - "-", - "(", - ")", - "~", - ":", - } - - // Postgres can handle "@" without any errors - // Also helps postgres in enabling search for EmailAddresses - if ss.DriverName() != model.DatabaseDriverPostgres { - chars = append(chars, "@") - } - - return chars +var specialSearchChars = []string{ + "<", + ">", + "+", + "-", + "(", + ")", + "~", + ":", } // computeBinaryParam returns whether the data source uses binary_parameters -// when using Postgres func (ss *SqlStore) computeBinaryParam() (bool, error) { - if ss.DriverName() != model.DatabaseDriverPostgres { - return false, nil - } - return DSNHasBinaryParam(*ss.settings.DataSource) } func (ss *SqlStore) computeDefaultTextSearchConfig() (string, error) { - if ss.DriverName() != model.DatabaseDriverPostgres { - return "", nil - } - var defaultTextSearchConfig string err := ss.GetMaster().Get(&defaultTextSearchConfig, `SHOW default_text_search_config`) return defaultTextSearchConfig, err @@ -395,14 +376,10 @@ func (ss *SqlStore) IsBinaryParamEnabled() bool { // that can be parsed by callers. func (ss *SqlStore) GetDbVersion(numerical bool) (string, error) { var sqlVersion string - if ss.DriverName() == model.DatabaseDriverPostgres { - if numerical { - sqlVersion = `SHOW server_version_num` - } else { - sqlVersion = `SHOW server_version` - } + if numerical { + sqlVersion = `SHOW server_version_num` } else { - return "", errors.New("Not supported driver") + sqlVersion = `SHOW server_version` } var version string @@ -952,19 +929,6 @@ func (ss *SqlStore) hasLicense() bool { return hasLicense } -func convertMySQLFullTextColumnsToPostgres(columnNames string) string { - columns := strings.Split(columnNames, ", ") - var concatenatedColumnNames strings.Builder - for i, c := range columns { - concatenatedColumnNames.WriteString(c) - if i < len(columns)-1 { - concatenatedColumnNames.WriteString(" || ' ' || ") - } - } - - return concatenatedColumnNames.String() -} - // IsDuplicate checks whether an error is a duplicate key error, which comes when processes are competing on creating the same // tables in the database. func IsDuplicate(err error) bool { @@ -981,15 +945,12 @@ func IsDuplicate(err error) bool { // ensureMinimumDBVersion gets the DB version and ensures it is // above the required minimum version requirements. func (ss *SqlStore) ensureMinimumDBVersion(ver string) (bool, error) { - switch *ss.settings.DriverName { - case model.DatabaseDriverPostgres: - intVer, err2 := strconv.Atoi(ver) - if err2 != nil { - return false, fmt.Errorf("cannot parse DB version: %v", err2) - } - if intVer < minimumRequiredPostgresVersion { - return false, fmt.Errorf("minimum Postgres version requirements not met. Found: %s, Wanted: %s", versionString(intVer, *ss.settings.DriverName), versionString(minimumRequiredPostgresVersion, *ss.settings.DriverName)) - } + intVer, err := strconv.Atoi(ver) + if err != nil { + return false, fmt.Errorf("cannot parse DB version: %v", err) + } + if intVer < minimumRequiredPostgresVersion { + return false, fmt.Errorf("minimum Postgres version requirements not met. Found: %s, Wanted: %s", versionString(intVer), versionString(minimumRequiredPostgresVersion)) } return true, nil } @@ -998,7 +959,7 @@ func (ss *SqlStore) ensureMinimumDBVersion(ver string) (bool, error) { // to a pretty-printed string. // Postgres doesn't follow three-part version numbers from 10.0 onwards: // https://www.postgresql.org/docs/13/libpq-status.html#LIBPQ-PQSERVERVERSION. -func versionString(v int, driver string) string { +func versionString(v int) string { minor := v % 10000 major := v / 10000 return strconv.Itoa(major) + "." + strconv.Itoa(minor) diff --git a/server/channels/store/sqlstore/store_test.go b/server/channels/store/sqlstore/store_test.go index c34bf2f79e7..a3be27e6ca3 100644 --- a/server/channels/store/sqlstore/store_test.go +++ b/server/channels/store/sqlstore/store_test.go @@ -763,28 +763,24 @@ func TestVersionString(t *testing.T) { versions := []struct { input int - driver string output string }{ { input: 100000, - driver: model.DatabaseDriverPostgres, output: "10.0", }, { input: 90603, - driver: model.DatabaseDriverPostgres, output: "9.603", }, { input: 120005, - driver: model.DatabaseDriverPostgres, output: "12.5", }, } for _, v := range versions { - out := versionString(v.input, v.driver) + out := versionString(v.input) assert.Equal(t, v.output, out) } } diff --git a/server/channels/store/sqlstore/team_store.go b/server/channels/store/sqlstore/team_store.go index 278fc6e66c1..28cb4726bfa 100644 --- a/server/channels/store/sqlstore/team_store.go +++ b/server/channels/store/sqlstore/team_store.go @@ -6,7 +6,6 @@ package sqlstore import ( "database/sql" "fmt" - "slices" "strings" sq "github.com/mattermost/squirrel" @@ -1614,19 +1613,11 @@ func (s SqlTeamStore) UserBelongsToTeams(userId string, teamIds []string) (bool, // UpdateMembersRole updates all the members of teamID in the adminIDs string array to be admins and sets all other // users as not being admin. -// It returns the list of userIDs whose roles got updated. -func (s SqlTeamStore) UpdateMembersRole(teamID string, adminIDs []string) (_ []*model.TeamMember, err error) { - transaction, err := s.GetMaster().Beginx() - if err != nil { - return nil, err - } - defer finalizeTransactionX(transaction, &err) - - // TODO: https://mattermost.atlassian.net/browse/MM-63368 - // On MySQL it's not possible to update a table and select from it in the same query. - // A SELECT and a UPDATE query are needed. - // Once we only support PostgreSQL, this can be done in a single query using RETURNING. - query, args, err := s.teamMembersQuery. +// It returns the list of members whose roles got updated. +func (s SqlTeamStore) UpdateMembersRole(teamID string, adminIDs []string) ([]*model.TeamMember, error) { + query := s.getQueryBuilder(). + Update("TeamMembers"). + Set("SchemeAdmin", sq.Case().When(sq.Eq{"UserId": adminIDs}, "true").Else("false")). Where(sq.Eq{"TeamId": teamID, "DeleteAt": 0}). Where(sq.Or{sq.Eq{"SchemeGuest": false}, sq.Expr("SchemeGuest IS NULL")}). Where( @@ -1642,42 +1633,14 @@ func (s SqlTeamStore) UpdateMembersRole(teamID string, adminIDs []string) (_ []* sq.NotEq{"UserId": adminIDs}, }, }, - ).ToSql() - if err != nil { - return nil, errors.Wrap(err, "team_tosql") - } + ). + Suffix("RETURNING " + strings.Join(teamMemberSliceColumns(), ", ")) var updatedMembers []*model.TeamMember - if err = transaction.Select(&updatedMembers, query, args...); err != nil { - return nil, errors.Wrap(err, "failed to get list of updated users") - } - - // Update SchemeAdmin field as the data from the SQL is not updated yet - for _, member := range updatedMembers { - if slices.Contains(adminIDs, member.UserId) { - member.SchemeAdmin = true - } else { - member.SchemeAdmin = false - } - } - - query, args, err = s.getQueryBuilder(). - Update("TeamMembers"). - Set("SchemeAdmin", sq.Case().When(sq.Eq{"UserId": adminIDs}, "true").Else("false")). - Where(sq.Eq{"TeamId": teamID, "DeleteAt": 0}). - Where(sq.Or{sq.Eq{"SchemeGuest": false}, sq.Expr("SchemeGuest IS NULL")}).ToSql() - if err != nil { - return nil, errors.Wrap(err, "team_tosql") - } - - if _, err = transaction.Exec(query, args...); err != nil { + if err := s.GetMaster().SelectBuilder(&updatedMembers, query); err != nil { return nil, errors.Wrap(err, "failed to update TeamMembers") } - if err = transaction.Commit(); err != nil { - return nil, errors.Wrap(err, "commit_transaction") - } - return updatedMembers, nil } diff --git a/server/channels/store/sqlstore/thread_store.go b/server/channels/store/sqlstore/thread_store.go index 9866560819f..4501eb5b279 100644 --- a/server/channels/store/sqlstore/thread_store.go +++ b/server/channels/store/sqlstore/thread_store.go @@ -5,7 +5,6 @@ package sqlstore import ( "database/sql" - "strconv" "time" sq "github.com/mattermost/squirrel" @@ -626,14 +625,8 @@ func (s *SqlThreadStore) MarkAllAsReadByChannels(userID string, channelIDs []str now := model.GetMillis() - var query sq.UpdateBuilder - if s.DriverName() == model.DatabaseDriverPostgres { - query = s.getQueryBuilder().Update("ThreadMemberships").From("Threads") - } else { - query = s.getQueryBuilder().Update("ThreadMemberships", "Threads") - } - - query = query.Set("LastViewed", now). + query := s.getQueryBuilder().Update("ThreadMemberships").From("Threads"). + Set("LastViewed", now). Set("UnreadMentions", 0). Set("LastUpdated", now). Where(sq.Eq{"ThreadMemberships.UserId": userID}). @@ -672,14 +665,7 @@ func (s *SqlThreadStore) MarkAllAsRead(userId string, threadIds []string) error func (s *SqlThreadStore) MarkAllAsReadByTeam(userId, teamId string) error { timestamp := model.GetMillis() - var query sq.UpdateBuilder - if s.DriverName() == model.DatabaseDriverPostgres { - query = s.getQueryBuilder().Update("ThreadMemberships").From("Threads") - } else { - query = s.getQueryBuilder().Update("ThreadMemberships", "Threads") - } - - query = query. + query := s.getQueryBuilder().Update("ThreadMemberships").From("Threads"). Where("Threads.PostId = ThreadMemberships.PostId"). Where(sq.Eq{"ThreadMemberships.UserId": userId}). Where(sq.Or{sq.Eq{"Threads.ThreadTeamId": teamId}, sq.Eq{"Threads.ThreadTeamId": ""}}). @@ -1111,30 +1097,19 @@ func (s *SqlThreadStore) SaveMultipleMemberships(memberships []*model.ThreadMemb } func (s *SqlThreadStore) updateThreadParticipantsForUserTx(trx *sqlxTxWrapper, postID, userID string) error { - if s.DriverName() == model.DatabaseDriverPostgres { - userIdParam, err := jsonArray([]string{userID}).Value() - if err != nil { - return err - } - if s.IsBinaryParamEnabled() { - userIdParam = AppendBinaryFlag(userIdParam.([]byte)) - } + userIdParam, err := jsonArray([]string{userID}).Value() + if err != nil { + return err + } + if s.IsBinaryParamEnabled() { + userIdParam = AppendBinaryFlag(userIdParam.([]byte)) + } - if _, err := trx.ExecRaw(`UPDATE Threads - SET participants = participants || $1::jsonb - WHERE postid=$2 - AND NOT participants ? $3`, userIdParam, postID, userID); err != nil { - return err - } - } else { - // CONCAT('$[', JSON_LENGTH(Participants), ']') just generates $[n] - // which is the positional syntax required for appending. - if _, err := trx.Exec(`UPDATE Threads - SET Participants = JSON_ARRAY_INSERT(Participants, CONCAT('$[', JSON_LENGTH(Participants), ']'), ?) - WHERE PostId=? - AND NOT JSON_CONTAINS(Participants, ?)`, userID, postID, strconv.Quote(userID)); err != nil { - return err - } + if _, err := trx.ExecRaw(`UPDATE Threads + SET participants = participants || $1::jsonb + WHERE postid=$2 + AND NOT participants ? $3`, userIdParam, postID, userID); err != nil { + return err } return nil diff --git a/server/channels/store/sqlstore/user_store.go b/server/channels/store/sqlstore/user_store.go index a0312cd5c73..cf673b51c05 100644 --- a/server/channels/store/sqlstore/user_store.go +++ b/server/channels/store/sqlstore/user_store.go @@ -640,8 +640,6 @@ func (us SqlUserStore) GetEtagForAllProfiles() string { } func (us SqlUserStore) GetAllProfiles(options *model.UserGetOptions) ([]*model.User, error) { - isPostgreSQL := us.DriverName() == model.DatabaseDriverPostgres - // Determine ordering based on Sort option - default to Username ASC for backwards compatibility orderBy := "Users.Username ASC" if options.Sort == "update_at_asc" { @@ -654,8 +652,8 @@ func (us SqlUserStore) GetAllProfiles(options *model.UserGetOptions) ([]*model.U query = applyViewRestrictionsFilter(query, options.ViewRestrictions, true) - query = applyRoleFilter(query, options.Role, isPostgreSQL) - query = applyMultiRoleFilters(query, options.Roles, []string{}, []string{}, isPostgreSQL) + query = applyRoleFilter(query, options.Role) + query = applyMultiRoleFilters(query, options.Roles, []string{}, []string{}) if options.Inactive { query = query.Where("Users.DeleteAt != 0") @@ -679,22 +677,16 @@ func (us SqlUserStore) GetAllProfiles(options *model.UserGetOptions) ([]*model.U return users, nil } -func applyRoleFilter(query sq.SelectBuilder, role string, isPostgreSQL bool) sq.SelectBuilder { +func applyRoleFilter(query sq.SelectBuilder, role string) sq.SelectBuilder { if role == "" { return query } - if isPostgreSQL { - roleParam := fmt.Sprintf("%%%s%%", sanitizeSearchTerm(role, "\\")) - return query.Where("Users.Roles LIKE LOWER(?)", roleParam) - } - - roleParam := fmt.Sprintf("%%%s%%", sanitizeSearchTerm(role, "*")) - - return query.Where("Users.Roles LIKE ? ESCAPE '*'", roleParam) + roleParam := fmt.Sprintf("%%%s%%", sanitizeSearchTerm(role, "\\")) + return query.Where("Users.Roles LIKE LOWER(?)", roleParam) } -func applyMultiRoleFilters(query sq.SelectBuilder, systemRoles []string, teamRoles []string, channelRoles []string, isPostgreSQL bool) sq.SelectBuilder { +func applyMultiRoleFilters(query sq.SelectBuilder, systemRoles []string, teamRoles []string, channelRoles []string) sq.SelectBuilder { sqOr := sq.Or{} if len(systemRoles) > 0 && systemRoles[0] != "" { @@ -706,11 +698,7 @@ func applyMultiRoleFilters(query sq.SelectBuilder, systemRoles []string, teamRol sqOr = append(sqOr, sq.Eq{"Users.Roles": role}) case model.SystemGuestRoleId, model.SystemAdminRoleId, model.SystemUserManagerRoleId, model.SystemReadOnlyAdminRoleId, model.SystemManagerRoleId: // If querying for any other roles search using a wildcard. - if isPostgreSQL { - sqOr = append(sqOr, sq.ILike{"Users.Roles": queryRole}) - } else { - sqOr = append(sqOr, sq.Like{"Users.Roles": queryRole}) - } + sqOr = append(sqOr, sq.ILike{"Users.Roles": queryRole}) } } } @@ -719,17 +707,9 @@ func applyMultiRoleFilters(query sq.SelectBuilder, systemRoles []string, teamRol for _, channelRole := range channelRoles { switch channelRole { case model.ChannelAdminRoleId: - if isPostgreSQL { - sqOr = append(sqOr, sq.And{sq.Eq{"cm.SchemeAdmin": true}, sq.NotILike{"Users.Roles": wildcardSearchTerm(model.SystemAdminRoleId)}}) - } else { - sqOr = append(sqOr, sq.And{sq.Eq{"cm.SchemeAdmin": true}, sq.NotLike{"Users.Roles": wildcardSearchTerm(model.SystemAdminRoleId)}}) - } + sqOr = append(sqOr, sq.And{sq.Eq{"cm.SchemeAdmin": true}, sq.NotILike{"Users.Roles": wildcardSearchTerm(model.SystemAdminRoleId)}}) case model.ChannelUserRoleId: - if isPostgreSQL { - sqOr = append(sqOr, sq.And{sq.Eq{"cm.SchemeUser": true}, sq.Eq{"cm.SchemeAdmin": false}, sq.NotILike{"Users.Roles": wildcardSearchTerm(model.SystemAdminRoleId)}}) - } else { - sqOr = append(sqOr, sq.And{sq.Eq{"cm.SchemeUser": true}, sq.Eq{"cm.SchemeAdmin": false}, sq.NotLike{"Users.Roles": wildcardSearchTerm(model.SystemAdminRoleId)}}) - } + sqOr = append(sqOr, sq.And{sq.Eq{"cm.SchemeUser": true}, sq.Eq{"cm.SchemeAdmin": false}, sq.NotILike{"Users.Roles": wildcardSearchTerm(model.SystemAdminRoleId)}}) case model.ChannelGuestRoleId: sqOr = append(sqOr, sq.Eq{"cm.SchemeGuest": true}) } @@ -740,17 +720,9 @@ func applyMultiRoleFilters(query sq.SelectBuilder, systemRoles []string, teamRol for _, teamRole := range teamRoles { switch teamRole { case model.TeamAdminRoleId: - if isPostgreSQL { - sqOr = append(sqOr, sq.And{sq.Eq{"tm.SchemeAdmin": true}, sq.NotILike{"Users.Roles": wildcardSearchTerm(model.SystemAdminRoleId)}}) - } else { - sqOr = append(sqOr, sq.And{sq.Eq{"tm.SchemeAdmin": true}, sq.NotLike{"Users.Roles": wildcardSearchTerm(model.SystemAdminRoleId)}}) - } + sqOr = append(sqOr, sq.And{sq.Eq{"tm.SchemeAdmin": true}, sq.NotILike{"Users.Roles": wildcardSearchTerm(model.SystemAdminRoleId)}}) case model.TeamUserRoleId: - if isPostgreSQL { - sqOr = append(sqOr, sq.And{sq.Eq{"tm.SchemeUser": true}, sq.Eq{"tm.SchemeAdmin": false}, sq.NotILike{"Users.Roles": wildcardSearchTerm(model.SystemAdminRoleId)}}) - } else { - sqOr = append(sqOr, sq.And{sq.Eq{"tm.SchemeUser": true}, sq.Eq{"tm.SchemeAdmin": false}, sq.NotLike{"Users.Roles": wildcardSearchTerm(model.SystemAdminRoleId)}}) - } + sqOr = append(sqOr, sq.And{sq.Eq{"tm.SchemeUser": true}, sq.Eq{"tm.SchemeAdmin": false}, sq.NotILike{"Users.Roles": wildcardSearchTerm(model.SystemAdminRoleId)}}) case model.TeamGuestRoleId: sqOr = append(sqOr, sq.Eq{"tm.SchemeGuest": true}) } @@ -821,7 +793,6 @@ func (us SqlUserStore) GetEtagForProfiles(teamId string) string { } func (us SqlUserStore) GetProfiles(options *model.UserGetOptions) ([]*model.User, error) { - isPostgreSQL := us.DriverName() == model.DatabaseDriverPostgres query := us.usersQuery. Join("TeamMembers tm ON ( tm.UserId = Users.Id AND tm.DeleteAt = 0 )"). Where("tm.TeamId = ?", options.InTeamId). @@ -830,8 +801,8 @@ func (us SqlUserStore) GetProfiles(options *model.UserGetOptions) ([]*model.User query = applyViewRestrictionsFilter(query, options.ViewRestrictions, true) - query = applyRoleFilter(query, options.Role, isPostgreSQL) - query = applyMultiRoleFilters(query, options.Roles, options.TeamRoles, options.ChannelRoles, isPostgreSQL) + query = applyRoleFilter(query, options.Role) + query = applyMultiRoleFilters(query, options.Roles, options.TeamRoles, options.ChannelRoles) if options.Inactive { query = query.Where("Users.DeleteAt != 0") @@ -868,7 +839,7 @@ func (us SqlUserStore) GetProfilesInChannel(options *model.UserGetOptions) ([]*m query = query.Where("Users.DeleteAt = 0") } - query = applyMultiRoleFilters(query, options.Roles, options.TeamRoles, options.ChannelRoles, us.DriverName() == model.DatabaseDriverPostgres) + query = applyMultiRoleFilters(query, options.Roles, options.TeamRoles, options.ChannelRoles) users := []*model.User{} if err := us.GetReplica().SelectBuilder(&users, query); err != nil { @@ -1030,7 +1001,6 @@ func (us SqlUserStore) GetProfilesNotInChannel(teamId string, channelId string, } func (us SqlUserStore) GetProfilesWithoutTeam(options *model.UserGetOptions) ([]*model.User, error) { - isPostgreSQL := us.DriverName() == model.DatabaseDriverPostgres query := us.usersQuery. Where(`( SELECT @@ -1046,7 +1016,7 @@ func (us SqlUserStore) GetProfilesWithoutTeam(options *model.UserGetOptions) ([] query = applyViewRestrictionsFilter(query, options.ViewRestrictions, true) - query = applyRoleFilter(query, options.Role, isPostgreSQL) + query = applyRoleFilter(query, options.Role) if options.Inactive { query = query.Where("Users.DeleteAt != 0") @@ -1448,17 +1418,12 @@ func (us SqlUserStore) Count(options model.UserCountOptions) (int64, error) { query = query.Where(sq.Or{sq.Eq{"Users.RemoteId": ""}, sq.Eq{"Users.RemoteId": nil}}) } - isPostgreSQL := us.DriverName() == model.DatabaseDriverPostgres if options.IncludeBotAccounts { if options.ExcludeRegularUsers { query = query.Join("Bots ON Users.Id = Bots.UserId") } } else { - if isPostgreSQL { - query = query.LeftJoin("Bots ON Users.Id = Bots.UserId").Where("Bots.UserId IS NULL") - } else { - query = query.Where(sq.Expr("Users.Id NOT IN (SELECT UserId FROM Bots)")) - } + query = query.LeftJoin("Bots ON Users.Id = Bots.UserId").Where("Bots.UserId IS NULL") if options.ExcludeRegularUsers { // Currently this doesn't make sense because it will always return 0 @@ -1472,11 +1437,9 @@ func (us SqlUserStore) Count(options model.UserCountOptions) (int64, error) { query = query.LeftJoin("ChannelMembers AS cm ON Users.Id = cm.UserId").Where("cm.ChannelId = ?", options.ChannelId) } query = applyViewRestrictionsFilter(query, options.ViewRestrictions, false) - query = applyMultiRoleFilters(query, options.Roles, options.TeamRoles, options.ChannelRoles, isPostgreSQL) + query = applyMultiRoleFilters(query, options.Roles, options.TeamRoles, options.ChannelRoles) - if isPostgreSQL { - query = query.PlaceholderFormat(sq.Dollar) - } + query = query.PlaceholderFormat(sq.Dollar) queryString, args, err := query.ToSql() if err != nil { @@ -1496,11 +1459,7 @@ func (us SqlUserStore) AnalyticsActiveCount(timePeriod int64, options model.User query := us.getQueryBuilder().Select("COUNT(*)").From("Status AS s").Where("LastActivityAt > ?", time) if !options.IncludeBotAccounts { - if us.DriverName() == model.DatabaseDriverPostgres { - query = query.LeftJoin("Bots ON s.UserId = Bots.UserId").Where("Bots.UserId IS NULL") - } else { - query = query.Where(sq.Expr("UserId NOT IN (SELECT UserId FROM Bots)")) - } + query = query.LeftJoin("Bots ON s.UserId = Bots.UserId").Where("Bots.UserId IS NULL") } if !options.IncludeRemoteUsers || !options.IncludeDeleted { @@ -1532,11 +1491,7 @@ func (us SqlUserStore) AnalyticsActiveCountForPeriod(startTime int64, endTime in query := us.getQueryBuilder().Select("COUNT(*)").From("Status AS s").Where("LastActivityAt > ? AND LastActivityAt <= ?", startTime, endTime) if !options.IncludeBotAccounts { - if us.DriverName() == model.DatabaseDriverPostgres { - query = query.LeftJoin("Bots ON s.UserId = Bots.UserId").Where("Bots.UserId IS NULL") - } else { - query = query.Where(sq.Expr("UserId NOT IN (SELECT UserId FROM Bots)")) - } + query = query.LeftJoin("Bots ON s.UserId = Bots.UserId").Where("Bots.UserId IS NULL") } if !options.IncludeRemoteUsers || !options.IncludeDeleted { @@ -1735,16 +1690,12 @@ func (us SqlUserStore) SearchNotInGroup(groupID string, term string, options *mo return us.performSearch(query, term, options) } -func generateSearchQuery(query sq.SelectBuilder, terms []string, fields []string, isPostgreSQL bool) sq.SelectBuilder { +func generateSearchQuery(query sq.SelectBuilder, terms []string, fields []string) sq.SelectBuilder { for _, term := range terms { searchFields := []string{} termArgs := []any{} for _, field := range fields { - if isPostgreSQL { - searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower(?) escape '*' ", field)) - } else { - searchFields = append(searchFields, fmt.Sprintf("%s LIKE ? escape '*' ", field)) - } + searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower(?) escape '*' ", field)) termArgs = append(termArgs, fmt.Sprintf("%%%s%%", strings.TrimLeft(term, "@"))) } searchFields = append(searchFields, "Id = ?") @@ -1773,17 +1724,15 @@ func (us SqlUserStore) performSearch(query sq.SelectBuilder, term string, option } } - isPostgreSQL := us.DriverName() == model.DatabaseDriverPostgres - - query = applyRoleFilter(query, options.Role, isPostgreSQL) - query = applyMultiRoleFilters(query, options.Roles, options.TeamRoles, options.ChannelRoles, isPostgreSQL) + query = applyRoleFilter(query, options.Role) + query = applyMultiRoleFilters(query, options.Roles, options.TeamRoles, options.ChannelRoles) if !options.AllowInactive { query = query.Where("Users.DeleteAt = 0") } if strings.TrimSpace(term) != "" { - query = generateSearchQuery(query, strings.Fields(term), searchType, isPostgreSQL) + query = generateSearchQuery(query, strings.Fields(term), searchType) } query = applyViewRestrictionsFilter(query, options.ViewRestrictions, true) @@ -1807,19 +1756,12 @@ func (us SqlUserStore) performSearch(query sq.SelectBuilder, term string, option func (us SqlUserStore) AnalyticsGetInactiveUsersCount() (int64, error) { query := us.getQueryBuilder(). Select("COUNT(Id)"). - From("Users") - if us.DriverName() == model.DatabaseDriverPostgres { - query = query.LeftJoin("Bots ON Users.ID = Bots.UserId"). - Where(sq.And{ - sq.Gt{"Users.DeleteAt": 0}, - sq.Eq{"Bots.UserId": nil}, - }) - } else { - query = query.Where(sq.And{ - sq.Expr("Users.Id NOT IN (SELECT UserId FROM Bots)"), + From("Users"). + LeftJoin("Bots ON Users.ID = Bots.UserId"). + Where(sq.And{ sq.Gt{"Users.DeleteAt": 0}, + sq.Eq{"Bots.UserId": nil}, }) - } var count int64 err := us.GetReplica().GetBuilder(&count, query) @@ -2354,11 +2296,7 @@ func (us SqlUserStore) IsEmpty(excludeBots bool) (bool, error) { From("Users") if excludeBots { - if us.DriverName() == model.DatabaseDriverPostgres { - builder = builder.LeftJoin("Bots ON Users.Id = Bots.UserId").Where("Bots.UserId IS NULL") - } else { - builder = builder.Where(sq.Expr("Users.Id NOT IN (SELECT UserId FROM Bots)")) - } + builder = builder.LeftJoin("Bots ON Users.Id = Bots.UserId").Where("Bots.UserId IS NULL") } builder = builder.Suffix(")") @@ -2409,19 +2347,14 @@ func (us SqlUserStore) GetUsersWithInvalidEmails(page int, perPage int, restrict } func (us SqlUserStore) RefreshPostStatsForUsers() error { - if us.DriverName() == model.DatabaseDriverPostgres { - if _, err := us.GetMaster().Exec("REFRESH MATERIALIZED VIEW poststats"); err != nil { - return errors.Wrap(err, "users_refresh_post_stats_exec") - } - } else { - mlog.Debug("Skipped running refresh post stats, only available on Postgres") + if _, err := us.GetMaster().Exec("REFRESH MATERIALIZED VIEW poststats"); err != nil { + return errors.Wrap(err, "users_refresh_post_stats_exec") } - return nil } -func applyUserReportFilter(query sq.SelectBuilder, filter *model.UserReportOptions, isPostgres bool) sq.SelectBuilder { - query = applyRoleFilter(query, filter.Role, isPostgres) +func applyUserReportFilter(query sq.SelectBuilder, filter *model.UserReportOptions) sq.SelectBuilder { + query = applyRoleFilter(query, filter.Role) if filter.HasNoTeam { query = query.Where(sq.Expr("Users.Id NOT IN (SELECT UserId FROM TeamMembers WHERE DeleteAt = 0)")) } else if filter.Team != "" { @@ -2436,25 +2369,20 @@ func applyUserReportFilter(query sq.SelectBuilder, filter *model.UserReportOptio } if strings.TrimSpace(filter.SearchTerm) != "" { - query = generateSearchQuery(query, strings.Fields(sanitizeSearchTerm(filter.SearchTerm, "*")), UserSearchTypeAll, isPostgres) + query = generateSearchQuery(query, strings.Fields(sanitizeSearchTerm(filter.SearchTerm, "*")), UserSearchTypeAll) } return query } func (us SqlUserStore) GetUserCountForReport(filter *model.UserReportOptions) (int64, error) { - isPostgres := us.DriverName() == model.DatabaseDriverPostgres query := us.getQueryBuilder(). Select("COUNT(Users.Id)"). - From("Users") - - if isPostgres { - query = query.LeftJoin("Bots ON Users.Id = Bots.UserId").Where("Bots.UserId IS NULL") - } else { - query = query.Where(sq.Expr("Users.Id NOT IN (SELECT UserId FROM Bots)")) - } + From("Users"). + LeftJoin("Bots ON Users.Id = Bots.UserId"). + Where("Bots.UserId IS NULL") - query = applyUserReportFilter(query, filter, isPostgres) + query = applyUserReportFilter(query, filter) queryStr, args, err := query.ToSql() if err != nil { return 0, errors.Wrap(err, "user_count_report_tosql") @@ -2468,15 +2396,12 @@ func (us SqlUserStore) GetUserCountForReport(filter *model.UserReportOptions) (i } func (us SqlUserStore) GetUserReport(filter *model.UserReportOptions) ([]*model.UserReportQuery, error) { - isPostgres := us.DriverName() == model.DatabaseDriverPostgres - selectColumns := append(getUsersColumns(), "MAX(s.LastActivityAt) AS LastStatusAt") - if isPostgres { - selectColumns = append(selectColumns, - "MAX(ps.LastPostDate) AS LastPostDate", - "COUNT(ps.Day) AS DaysActive", - "SUM(ps.NumPosts) AS TotalPosts", - ) - } + selectColumns := append(getUsersColumns(), + "MAX(s.LastActivityAt) AS LastStatusAt", + "MAX(ps.LastPostDate) AS LastPostDate", + "COUNT(ps.Day) AS DaysActive", + "SUM(ps.NumPosts) AS TotalPosts", + ) sortDirection := "ASC" if filter.SortDesc { @@ -2522,24 +2447,22 @@ func (us SqlUserStore) GetUserReport(filter *model.UserReportOptions) ([]*model. query = query.Limit(uint64(filter.PageSize)) } - if isPostgres { - joinSql := sq.And{} - if filter.StartAt > 0 { - startDate := time.UnixMilli(filter.StartAt) - joinSql = append(joinSql, sq.GtOrEq{"ps.Day": startDate.Format("2006-01-02")}) - } - if filter.EndAt > 0 { - endDate := time.UnixMilli(filter.EndAt) - joinSql = append(joinSql, sq.Lt{"ps.Day": endDate.Format("2006-01-02")}) - } - sql, args, err := joinSql.ToSql() - if err != nil { - return nil, err - } - query = query.LeftJoin("PostStats ps ON ps.UserId = Users.Id AND "+sql, args...) + joinSql := sq.And{} + if filter.StartAt > 0 { + startDate := time.UnixMilli(filter.StartAt) + joinSql = append(joinSql, sq.GtOrEq{"ps.Day": startDate.Format("2006-01-02")}) + } + if filter.EndAt > 0 { + endDate := time.UnixMilli(filter.EndAt) + joinSql = append(joinSql, sq.Lt{"ps.Day": endDate.Format("2006-01-02")}) + } + sql, args, err := joinSql.ToSql() + if err != nil { + return nil, err } + query = query.LeftJoin("PostStats ps ON ps.UserId = Users.Id AND "+sql, args...) - query = applyUserReportFilter(query, filter, isPostgres) + query = applyUserReportFilter(query, filter) parentQuery := query // If we're going a page back... @@ -2560,7 +2483,7 @@ func (us SqlUserStore) GetUserReport(filter *model.UserReportOptions) ([]*model. } userResults := []*model.UserReportQuery{} - err := us.GetReplica().SelectBuilder(&userResults, parentQuery) + err = us.GetReplica().SelectBuilder(&userResults, parentQuery) if err != nil { return nil, errors.Wrap(err, "failed to get users for reporting") } diff --git a/server/channels/store/sqlstore/utils.go b/server/channels/store/sqlstore/utils.go index 72a6ce5452d..c1064af7f5a 100644 --- a/server/channels/store/sqlstore/utils.go +++ b/server/channels/store/sqlstore/utils.go @@ -159,11 +159,6 @@ func trimInput(input string) string { return input } -// Returns the column name for PostgreSQL. -func quoteColumnName(driver string, columnName string) string { - return columnName -} - // scanRowsIntoMap scans SQL rows into a map, using a provided scanner function to extract key-value pairs func scanRowsIntoMap[K comparable, V any](rows *sql.Rows, scanner func(rows *sql.Rows) (K, V, error), defaults map[K]V) (map[K]V, error) { results := make(map[K]V, len(defaults)) diff --git a/server/channels/store/storetest/post_store.go b/server/channels/store/storetest/post_store.go index 7855e55f52f..4596dddca72 100644 --- a/server/channels/store/storetest/post_store.go +++ b/server/channels/store/storetest/post_store.go @@ -5973,8 +5973,7 @@ func testGetPostsForReporting(t *testing.T, rctx request.CTX, ss store.Store, s // // For reporting queries, we expect the query to use index seeks, not table scans // - // Note: The actual query plan depends on the database (PostgreSQL vs MySQL), - // data distribution, and statistics. This test just verifies the query executes + // Note: The actual query plan depends on data distribution and statistics. This test just verifies the query executes // efficiently by checking that it completes in a reasonable time. // Create a larger dataset to better test index usage diff --git a/server/channels/testlib/helper.go b/server/channels/testlib/helper.go index ea8b7932daa..38d0d2242b4 100644 --- a/server/channels/testlib/helper.go +++ b/server/channels/testlib/helper.go @@ -254,7 +254,6 @@ func (h *MainHelper) setupResources() { // // Re-generate the files with: // pg_dump -a -h localhost -U mmuser -d <> --no-comments --inserts -t roles -t systems -// mysqldump -u root -p <> --no-create-info --extended-insert=FALSE Systems Roles // And keep only the permission related rows in the systems table output. func preloadMigrations(driverName string, sqlStore *sqlstore.SqlStore) { var buf []byte diff --git a/server/channels/testlib/testdata/boards_mysql_migration_warmup.sql b/server/channels/testlib/testdata/boards_mysql_migration_warmup.sql deleted file mode 100644 index d279598e928..00000000000 --- a/server/channels/testlib/testdata/boards_mysql_migration_warmup.sql +++ /dev/null @@ -1,41 +0,0 @@ --- MySQL dump 10.13 Distrib 5.7.12, for Linux (x86_64) --- --- Host: localhost Database: mattermost_test --- ------------------------------------------------------ --- Server version 5.7.12 - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - --- --- Dumping data for table `focalboard_system_settings` --- - -LOCK TABLES `focalboard_system_settings` WRITE; -/*!40000 ALTER TABLE `focalboard_system_settings` DISABLE KEYS */; -INSERT INTO `focalboard_system_settings` VALUES ('CategoryUuidIdMigrationComplete','true'); -INSERT INTO `focalboard_system_settings` VALUES ('DeDuplicateCategoryBoardTableComplete','true'); -INSERT INTO `focalboard_system_settings` VALUES ('DeletedMembershipBoardsMigrationComplete','true'); -INSERT INTO `focalboard_system_settings` VALUES ('TeamLessBoardsMigrationComplete','true'); -INSERT INTO `focalboard_system_settings` VALUES ('UniqueIDsMigrationComplete','true'); -/*!40000 ALTER TABLE `focalboard_system_settings` ENABLE KEYS */; -UNLOCK TABLES; -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - --- Dump completed on 2023-03-31 11:37:35 diff --git a/server/channels/testlib/testdata/mysql_migration_warmup.sql b/server/channels/testlib/testdata/mysql_migration_warmup.sql deleted file mode 100644 index b76f793c431..00000000000 --- a/server/channels/testlib/testdata/mysql_migration_warmup.sql +++ /dev/null @@ -1,106 +0,0 @@ --- MySQL dump 10.13 Distrib 8.0.23, for Linux (x86_64) --- --- Host: localhost Database: dbwidnrtyyj7nhxnj5nkq5s7te7c --- ------------------------------------------------------ --- Server version 8.0.23 - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!50503 SET NAMES utf8mb4 */; -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - --- --- Dumping data for table `Systems` --- - -LOCK TABLES `Systems` WRITE; -/*!40000 ALTER TABLE `Systems` DISABLE KEYS */; -INSERT INTO `Systems` VALUES ('about_subsection_permissions','true'); -INSERT INTO `Systems` VALUES ('add_billing_permissions','true'); -INSERT INTO `Systems` VALUES ('add_bot_permissions','true'); -INSERT INTO `Systems` VALUES ('add_convert_channel_permissions','true'); -INSERT INTO `Systems` VALUES ('add_manage_guests_permissions','true'); -INSERT INTO `Systems` VALUES ('add_system_console_permissions','true'); -INSERT INTO `Systems` VALUES ('add_system_roles_permissions','true'); -INSERT INTO `Systems` VALUES ('add_use_group_mentions_permission','true'); -INSERT INTO `Systems` VALUES ('AdvancedPermissionsMigrationComplete','true'); -INSERT INTO `Systems` VALUES ('apply_channel_manage_delete_to_channel_user','true'); -INSERT INTO `Systems` VALUES ('authentication_subsection_permissions','true'); -INSERT INTO `Systems` VALUES ('channel_moderations_permissions','true'); -INSERT INTO `Systems` VALUES ('compliance_subsection_permissions','true'); -INSERT INTO `Systems` VALUES ('ContentExtractionConfigDefaultTrueMigrationComplete','true'); -INSERT INTO `Systems` VALUES ('custom_groups_permissions','true'); -INSERT INTO `Systems` VALUES ('CustomGroupAdminRoleCreationMigrationComplete','true'); -INSERT INTO `Systems` VALUES ('download_compliance_export_results','true'); -INSERT INTO `Systems` VALUES ('emoji_permissions_split','true'); -INSERT INTO `Systems` VALUES ('EmojisPermissionsMigrationComplete','true'); -INSERT INTO `Systems` VALUES ('environment_subsection_permissions','true'); -INSERT INTO `Systems` VALUES ('experimental_subsection_permissions','true'); -INSERT INTO `Systems` VALUES ('GuestRolesCreationMigrationComplete','true'); -INSERT INTO `Systems` VALUES ('integrations_subsection_permissions','true'); -INSERT INTO `Systems` VALUES ('list_join_public_private_teams','true'); -INSERT INTO `Systems` VALUES ('manage_secure_connections_permissions','true'); -INSERT INTO `Systems` VALUES ('manage_shared_channel_permissions','true'); -INSERT INTO `Systems` VALUES ('PlaybookRolesCreationMigrationComplete','true'); -INSERT INTO `Systems` VALUES ('playbooks_manage_roles','true'); -INSERT INTO `Systems` VALUES ('playbooks_permissions','true'); -INSERT INTO `Systems` VALUES ('remove_channel_manage_delete_from_team_user','true'); -INSERT INTO `Systems` VALUES ('remove_permanent_delete_user','true'); -INSERT INTO `Systems` VALUES ('reporting_subsection_permissions','true'); -INSERT INTO `Systems` VALUES ('site_subsection_permissions','true'); -INSERT INTO `Systems` VALUES ('SystemConsoleRolesCreationMigrationComplete','true'); -INSERT INTO `Systems` VALUES ('test_email_ancillary_permission','true'); -INSERT INTO `Systems` VALUES ('Version','5.31.0'); -INSERT INTO `Systems` VALUES ('view_members_new_permission','true'); -INSERT INTO `Systems` VALUES ('webhook_permissions_split','true'); -/*!40000 ALTER TABLE `Systems` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Dumping data for table `Roles` --- - -LOCK TABLES `Roles` WRITE; -/*!40000 ALTER TABLE `Roles` DISABLE KEYS */; -INSERT INTO `Roles` VALUES ('3ndsqn4sbbyjxpzccrzmzejstw','team_guest','authentication.roles.team_guest.name','authentication.roles.team_guest.description',1605167829008,1662271986894,0,' view_team',1,1); -INSERT INTO `Roles` VALUES ('44bq9f9s93b7f811ex5r1b4s1w','system_custom_group_admin','authentication.roles.system_custom_group_admin.name','authentication.roles.system_custom_group_admin.description',1662271985879,1662271986897,0,' manage_custom_group_members create_custom_group edit_custom_group delete_custom_group',0,1); -INSERT INTO `Roles` VALUES ('6jaz4y4nmjnxunkmogjf95fiha','system_user_manager','authentication.roles.system_user_manager.name','authentication.roles.system_user_manager.description',0,1662271986902,0,' delete_public_channel sysconsole_write_user_management_channels list_public_teams sysconsole_read_authentication_ldap sysconsole_write_user_management_groups manage_private_channel_members sysconsole_read_user_management_permissions sysconsole_read_authentication_password read_channel join_private_teams manage_team sysconsole_read_user_management_teams sysconsole_read_authentication_email sysconsole_write_user_management_teams read_public_channel_groups list_private_teams convert_private_channel_to_public manage_team_roles convert_public_channel_to_private sysconsole_read_authentication_openid view_team add_user_to_team read_ldap_sync_job read_public_channel test_ldap manage_private_channel_properties delete_private_channel manage_channel_roles sysconsole_read_authentication_guest_access sysconsole_read_user_management_channels sysconsole_read_user_management_groups manage_public_channel_members sysconsole_read_authentication_saml remove_user_from_team join_public_teams manage_public_channel_properties sysconsole_read_authentication_mfa sysconsole_read_authentication_signup read_private_channel_groups',0,1); -INSERT INTO `Roles` VALUES ('6pahsh5hg7rpjfhz4f5c1wsbfw','team_admin','authentication.roles.team_admin.name','authentication.roles.team_admin.description',0,1662271986906,0,' remove_user_from_team manage_slash_commands manage_team_roles delete_others_posts manage_others_slash_commands import_team manage_others_outgoing_webhooks convert_private_channel_to_public delete_post playbook_private_manage_roles convert_public_channel_to_private manage_channel_roles playbook_public_manage_roles manage_outgoing_webhooks manage_others_incoming_webhooks manage_incoming_webhooks manage_team',1,1); -INSERT INTO `Roles` VALUES ('c7oo8yeiojfu8xjyuyxn3fhxpc','team_post_all','authentication.roles.team_post_all.name','authentication.roles.team_post_all.description',0,1662271986910,0,' create_post use_channel_mentions',0,1); -INSERT INTO `Roles` VALUES ('cmqctq1egt877y9ua9pdsknoiw','team_post_all_public','authentication.roles.team_post_all_public.name','authentication.roles.team_post_all_public.description',0,1662271986914,0,' create_post_public use_channel_mentions',0,1); -INSERT INTO `Roles` VALUES ('dmmkxxmi3b8pdgcq9pjtf6mfao','playbook_member','authentication.roles.playbook_member.name','authentication.roles.playbook_member.description',1662271985811,1662271986918,0,' playbook_private_manage_members playbook_private_manage_properties run_create playbook_public_view playbook_public_manage_members playbook_public_manage_properties playbook_private_view',1,1); -INSERT INTO `Roles` VALUES ('dwjkqj9bj7r4xr8zb18z3tg53y','playbook_admin','authentication.roles.playbook_admin.name','authentication.roles.playbook_admin.description',1662271985841,1662271986921,0,' playbook_private_manage_roles playbook_private_manage_properties playbook_public_make_private playbook_public_manage_members playbook_public_manage_roles playbook_public_manage_properties playbook_private_manage_members',1,1); -INSERT INTO `Roles` VALUES ('hh56iy3patffuc3h76soondcga','channel_admin','authentication.roles.channel_admin.name','authentication.roles.channel_admin.description',0,1662271986924,0,' manage_channel_roles use_group_mentions',1,1); -INSERT INTO `Roles` VALUES ('hkcrew7wttb5fbuw3ime6g7nzc','system_read_only_admin','authentication.roles.system_read_only_admin.name','authentication.roles.system_read_only_admin.description',0,1662271986928,0,' sysconsole_read_environment_database sysconsole_read_experimental_features sysconsole_read_compliance_compliance_export sysconsole_read_environment_performance_monitoring sysconsole_read_environment_file_storage sysconsole_read_user_management_channels read_public_channel_groups read_elasticsearch_post_aggregation_job sysconsole_read_integrations_integration_management sysconsole_read_environment_push_notification_server read_compliance_export_job sysconsole_read_user_management_teams sysconsole_read_environment_logging sysconsole_read_about_edition_and_license sysconsole_read_site_customization sysconsole_read_reporting_site_statistics sysconsole_read_site_emoji sysconsole_read_authentication_guest_access test_ldap read_audits sysconsole_read_site_posts download_compliance_export_result sysconsole_read_compliance_compliance_monitoring sysconsole_read_site_announcement_banner sysconsole_read_integrations_gif sysconsole_read_authentication_email sysconsole_read_site_file_sharing_and_downloads sysconsole_read_compliance_data_retention_policy read_channel sysconsole_read_experimental_feature_flags sysconsole_read_environment_image_proxy view_team sysconsole_read_authentication_openid sysconsole_read_environment_web_server sysconsole_read_integrations_cors read_ldap_sync_job sysconsole_read_authentication_saml get_analytics read_private_channel_groups sysconsole_read_reporting_team_statistics sysconsole_read_compliance_custom_terms_of_service sysconsole_read_authentication_ldap sysconsole_read_environment_smtp read_other_users_teams sysconsole_read_user_management_permissions sysconsole_read_environment_session_lengths read_public_channel read_data_retention_job sysconsole_read_user_management_groups sysconsole_read_environment_high_availability sysconsole_read_site_public_links sysconsole_read_authentication_password sysconsole_read_environment_rate_limiting list_public_teams sysconsole_read_site_users_and_teams sysconsole_read_authentication_signup get_logs read_license_information sysconsole_read_site_notices list_private_teams read_elasticsearch_post_indexing_job sysconsole_read_site_notifications sysconsole_read_authentication_mfa sysconsole_read_integrations_bot_accounts sysconsole_read_reporting_server_logs sysconsole_read_site_localization sysconsole_read_environment_elasticsearch sysconsole_read_user_management_users sysconsole_read_plugins sysconsole_read_environment_developer',0,1); -INSERT INTO `Roles` VALUES ('iiwt9pt6wiyb9e1enixtxs5yme','run_admin','authentication.roles.run_admin.name','authentication.roles.run_admin.description',1662271985864,1662271986932,0,' run_manage_properties run_manage_members',1,1); -INSERT INTO `Roles` VALUES ('jg1f1xfh3bb73pua938orwg9ie','system_guest','authentication.roles.global_guest.name','authentication.roles.global_guest.description',1605167829015,1662271986937,0,' create_direct_channel create_group_channel',1,1); -INSERT INTO `Roles` VALUES ('k891n5tpd3n9peue79azejjocy','system_post_all_public','authentication.roles.system_post_all_public.name','authentication.roles.system_post_all_public.description',0,1662271986941,0,' use_channel_mentions create_post_public',0,1); -INSERT INTO `Roles` VALUES ('kb6r9i58x7dxdb3srfohd66sse','system_admin','authentication.roles.global_admin.name','authentication.roles.global_admin.description',0,1662271986948,0,' list_public_teams edit_brand manage_private_channel_properties sysconsole_read_user_management_teams playbook_public_create manage_others_bots invalidate_caches manage_shared_channels sysconsole_write_environment_logging manage_others_outgoing_webhooks sysconsole_read_reporting_team_statistics sysconsole_read_plugins list_team_channels use_group_mentions sysconsole_read_site_users_and_teams sysconsole_write_site_localization get_analytics manage_team_roles sysconsole_read_site_localization edit_post sysconsole_write_user_management_channels test_elasticsearch list_private_teams add_ldap_public_cert join_public_teams manage_slash_commands manage_others_incoming_webhooks manage_public_channel_members sysconsole_read_environment_elasticsearch sysconsole_write_site_customization delete_others_emojis run_manage_members create_emojis sysconsole_write_authentication_email sysconsole_write_compliance_compliance_export add_saml_private_cert create_bot sysconsole_write_environment_rate_limiting add_saml_public_cert edit_other_users sysconsole_write_integrations_integration_management read_user_access_token create_elasticsearch_post_indexing_job sysconsole_write_user_management_users assign_system_admin_role sysconsole_write_user_management_groups sysconsole_read_authentication_guest_access sysconsole_write_about_edition_and_license sysconsole_read_authentication_ldap sysconsole_read_experimental_feature_flags sysconsole_read_integrations_cors sysconsole_read_user_management_groups join_public_channels sysconsole_read_experimental_features test_ldap sysconsole_write_environment_elasticsearch sysconsole_write_reporting_server_logs sysconsole_read_environment_image_proxy sysconsole_read_site_announcement_banner sysconsole_read_reporting_site_statistics sysconsole_write_authentication_mfa sysconsole_read_authentication_openid playbook_public_manage_members delete_emojis sysconsole_write_environment_file_storage sysconsole_write_reporting_site_statistics playbook_private_manage_members import_team sysconsole_write_environment_web_server sysconsole_write_authentication_password read_public_channel_groups create_compliance_export_job sysconsole_read_authentication_password list_users_without_team sysconsole_read_authentication_mfa add_ldap_private_cert create_data_retention_job read_license_information sysconsole_write_authentication_signup sysconsole_read_environment_push_notification_server edit_others_posts download_compliance_export_result create_ldap_sync_job sysconsole_write_authentication_ldap sysconsole_write_plugins read_data_retention_job sysconsole_write_compliance_data_retention_policy sysconsole_read_site_public_links manage_bots manage_system sysconsole_write_compliance_custom_terms_of_service playbook_public_manage_roles playbook_public_manage_properties playbook_private_create sysconsole_read_authentication_email promote_guest get_saml_cert_status add_user_to_team sysconsole_write_site_users_and_teams create_custom_group manage_private_channel_members read_jobs sysconsole_write_experimental_features read_other_users_teams sysconsole_write_reporting_team_statistics sysconsole_read_environment_file_storage sysconsole_read_site_file_sharing_and_downloads playbook_private_make_public playbook_public_view create_user_access_token create_public_channel read_channel sysconsole_read_user_management_channels sysconsole_read_user_management_permissions read_public_channel sysconsole_read_compliance_custom_terms_of_service sysconsole_write_site_emoji sysconsole_read_integrations_gif sysconsole_read_site_customization sysconsole_write_integrations_cors invite_user create_direct_channel sysconsole_write_user_management_teams run_create manage_custom_group_members read_ldap_sync_job sysconsole_read_site_notifications playbook_private_manage_properties sysconsole_read_integrations_bot_accounts convert_public_channel_to_private invalidate_email_invite reload_config get_saml_metadata_from_idp manage_secure_connections delete_private_channel sysconsole_read_about_edition_and_license convert_private_channel_to_public sysconsole_read_environment_developer recycle_database_connections remove_saml_private_cert manage_oauth sysconsole_write_environment_database sysconsole_write_site_notifications sysconsole_write_authentication_guest_access sysconsole_write_compliance_compliance_monitoring sysconsole_write_environment_image_proxy create_post_public manage_jobs remove_user_from_team delete_others_posts create_post_ephemeral playbook_private_view create_elasticsearch_post_aggregation_job remove_reaction add_reaction sysconsole_write_environment_high_availability sysconsole_write_authentication_openid sysconsole_write_user_management_permissions add_saml_idp_cert sysconsole_read_site_posts view_members sysconsole_write_environment_smtp sysconsole_read_authentication_saml create_post use_channel_mentions create_team playbook_private_manage_roles get_public_link sysconsole_write_billing manage_system_wide_oauth sysconsole_read_environment_database sysconsole_write_environment_session_lengths run_manage_properties sysconsole_write_authentication_saml sysconsole_read_environment_web_server sysconsole_read_environment_rate_limiting manage_public_channel_properties create_group_channel sysconsole_read_compliance_data_retention_policy sysconsole_read_environment_high_availability manage_others_slash_commands sysconsole_read_compliance_compliance_export delete_custom_group sysconsole_read_user_management_system_roles purge_elasticsearch_indexes view_team sysconsole_read_environment_performance_monitoring manage_channel_roles playbook_public_make_private remove_saml_public_cert demote_to_guest sysconsole_write_environment_performance_monitoring read_audits sysconsole_write_site_announcement_banner upload_file revoke_user_access_token read_others_bots test_email read_elasticsearch_post_aggregation_job sysconsole_read_compliance_compliance_monitoring join_private_teams delete_post sysconsole_write_site_public_links manage_team edit_custom_group sysconsole_write_experimental_feature_flags sysconsole_write_user_management_system_roles remove_others_reactions manage_license_information sysconsole_read_authentication_signup read_compliance_export_job sysconsole_write_environment_developer remove_saml_idp_cert manage_incoming_webhooks sysconsole_read_site_emoji assign_bot sysconsole_write_integrations_gif sysconsole_read_user_management_users delete_public_channel manage_outgoing_webhooks sysconsole_write_site_posts remove_ldap_private_cert sysconsole_write_site_file_sharing_and_downloads sysconsole_read_integrations_integration_management sysconsole_read_environment_logging test_site_url sysconsole_read_environment_session_lengths read_elasticsearch_post_indexing_job sysconsole_read_billing sysconsole_read_site_notices sysconsole_read_reporting_server_logs sysconsole_write_integrations_bot_accounts sysconsole_write_site_notices create_private_channel read_private_channel_groups run_view read_bots manage_roles test_s3 sysconsole_write_environment_push_notification_server get_logs invite_guest remove_ldap_public_cert sysconsole_read_environment_smtp',1,1); -INSERT INTO `Roles` VALUES ('km7kijhdtjbajquwu36uqneyoc','system_post_all','authentication.roles.system_post_all.name','authentication.roles.system_post_all.description',0,1662271986953,0,' create_post use_channel_mentions',0,1); -INSERT INTO `Roles` VALUES ('no7s4436sjbzzqjpupg85mszty','custom_group_user','authentication.roles.custom_group_user.name','authentication.roles.custom_group_user.description',1662271985801,1662271986956,0,'',0,0); -INSERT INTO `Roles` VALUES ('qo7e17c1m3rezyjqx5iq9dpmxe','system_manager','authentication.roles.system_manager.name','authentication.roles.system_manager.description',0,1662271986960,0,' sysconsole_write_environment_image_proxy sysconsole_read_environment_developer read_ldap_sync_job sysconsole_read_reporting_team_statistics recycle_database_connections get_logs read_private_channel_groups test_elasticsearch sysconsole_read_environment_logging purge_elasticsearch_indexes sysconsole_write_site_posts sysconsole_read_environment_database sysconsole_read_environment_performance_monitoring manage_team sysconsole_read_authentication_password sysconsole_write_site_users_and_teams sysconsole_read_user_management_channels sysconsole_write_environment_rate_limiting sysconsole_write_site_notifications read_license_information edit_brand sysconsole_read_plugins sysconsole_read_environment_high_availability sysconsole_read_environment_file_storage sysconsole_read_environment_elasticsearch sysconsole_write_environment_web_server sysconsole_write_environment_smtp sysconsole_write_environment_performance_monitoring sysconsole_write_environment_session_lengths sysconsole_write_user_management_groups convert_private_channel_to_public manage_private_channel_properties sysconsole_read_site_posts list_private_teams sysconsole_read_authentication_ldap sysconsole_read_authentication_guest_access sysconsole_read_site_emoji sysconsole_write_integrations_integration_management convert_public_channel_to_private manage_private_channel_members read_elasticsearch_post_aggregation_job manage_team_roles sysconsole_write_site_file_sharing_and_downloads read_channel read_public_channel sysconsole_read_authentication_openid add_user_to_team sysconsole_write_environment_developer sysconsole_write_site_localization sysconsole_read_about_edition_and_license test_s3 reload_config sysconsole_write_environment_elasticsearch test_site_url sysconsole_write_site_announcement_banner get_analytics sysconsole_read_environment_push_notification_server sysconsole_read_authentication_signup test_email sysconsole_write_integrations_bot_accounts sysconsole_write_integrations_cors view_team sysconsole_write_integrations_gif sysconsole_read_site_notices sysconsole_read_environment_image_proxy sysconsole_read_integrations_cors sysconsole_write_environment_push_notification_server join_public_teams test_ldap create_elasticsearch_post_aggregation_job sysconsole_read_environment_session_lengths sysconsole_write_environment_file_storage manage_public_channel_members sysconsole_write_site_customization sysconsole_read_site_announcement_banner sysconsole_read_environment_smtp sysconsole_write_user_management_teams delete_public_channel sysconsole_write_environment_logging read_public_channel_groups sysconsole_read_site_users_and_teams sysconsole_read_reporting_site_statistics sysconsole_read_site_localization sysconsole_read_site_customization sysconsole_read_environment_rate_limiting sysconsole_read_environment_web_server sysconsole_write_user_management_permissions sysconsole_read_site_file_sharing_and_downloads sysconsole_write_site_public_links sysconsole_read_site_public_links sysconsole_read_authentication_email read_elasticsearch_post_indexing_job sysconsole_read_authentication_saml remove_user_from_team delete_private_channel sysconsole_write_user_management_channels sysconsole_read_reporting_server_logs sysconsole_read_integrations_bot_accounts sysconsole_read_user_management_teams list_public_teams create_elasticsearch_post_indexing_job sysconsole_write_site_emoji invalidate_caches sysconsole_read_integrations_integration_management sysconsole_write_environment_high_availability sysconsole_read_user_management_permissions join_private_teams manage_channel_roles sysconsole_write_site_notices manage_public_channel_properties sysconsole_write_environment_database sysconsole_read_site_notifications sysconsole_read_user_management_groups sysconsole_read_integrations_gif sysconsole_read_authentication_mfa',0,1); -INSERT INTO `Roles` VALUES ('rkr97ikkh7fixy86qsoo5rqm4c','system_user_access_token','authentication.roles.system_user_access_token.name','authentication.roles.system_user_access_token.description',0,1662271986965,0,' create_user_access_token read_user_access_token revoke_user_access_token',0,1); -INSERT INTO `Roles` VALUES ('rxzdk5irm7rcffcfej9e33kqeo','team_user','authentication.roles.team_user.name','authentication.roles.team_user.description',0,1662271986968,0,' invite_user view_team read_public_channel playbook_public_create add_user_to_team playbook_private_create create_private_channel list_team_channels create_public_channel join_public_channels',1,1); -INSERT INTO `Roles` VALUES ('x768jnyzw3rkfx7xb66ehcac6o','channel_user','authentication.roles.channel_user.name','authentication.roles.channel_user.description',0,1662271986972,0,' manage_public_channel_properties create_post manage_private_channel_properties delete_public_channel manage_private_channel_members get_public_link delete_post delete_private_channel upload_file edit_post remove_reaction use_channel_mentions add_reaction read_channel manage_public_channel_members',1,1); -INSERT INTO `Roles` VALUES ('ynn8aynsn7n1trtbuq6p4cyzhe','channel_guest','authentication.roles.channel_guest.name','authentication.roles.channel_guest.description',1605167829001,1662271986975,0,' read_channel add_reaction remove_reaction upload_file edit_post create_post use_channel_mentions',1,1); -INSERT INTO `Roles` VALUES ('yqyby79r9jggxg7a9dnenuawmo','run_member','authentication.roles.run_member.name','authentication.roles.run_member.description',1662271985813,1662271986979,0,' run_view',1,1); -INSERT INTO `Roles` VALUES ('zzehkfnp67bg5g1owh6eptdcxc','system_user','authentication.roles.global_user.name','authentication.roles.global_user.description',0,1662271986983,0,' create_emojis join_public_teams list_public_teams edit_custom_group delete_emojis create_team create_group_channel manage_custom_group_members view_members delete_custom_group create_custom_group create_direct_channel',1,1); -/*!40000 ALTER TABLE `Roles` ENABLE KEYS */; -UNLOCK TABLES; -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - --- Dump completed on 2022-09-04 6:13:45 diff --git a/server/cmd/mmctl/commands/config.go b/server/cmd/mmctl/commands/config.go index add760f203d..b522eb5c3f7 100644 --- a/server/cmd/mmctl/commands/config.go +++ b/server/cmd/mmctl/commands/config.go @@ -45,7 +45,7 @@ var ConfigSetCmd = &cobra.Command{ Use: "set", Short: "Set config setting", Long: "Sets the value of a config setting by its name in dot notation. Accepts multiple values for array settings", - Example: "config set SqlSettings.DriverName mysql\nconfig set SqlSettings.DataSourceReplicas \"replica1\" \"replica2\"", + Example: "config set SqlSettings.DriverName postgres\nconfig set SqlSettings.DataSourceReplicas \"replica1\" \"replica2\"", Args: cobra.MinimumNArgs(2), RunE: withClient(configSetCmdF), } diff --git a/server/cmd/mmctl/docs/mmctl_config_set.rst b/server/cmd/mmctl/docs/mmctl_config_set.rst index 1193d82ba3f..3571478fa9a 100644 --- a/server/cmd/mmctl/docs/mmctl_config_set.rst +++ b/server/cmd/mmctl/docs/mmctl_config_set.rst @@ -20,7 +20,7 @@ Examples :: - config set SqlSettings.DriverName mysql + config set SqlSettings.DriverName postgres config set SqlSettings.DataSourceReplicas "replica1" "replica2" Options diff --git a/server/config/database.go b/server/config/database.go index 82619039ac1..7708b43eb52 100644 --- a/server/config/database.go +++ b/server/config/database.go @@ -84,8 +84,6 @@ func NewDatabaseStore(dsn string) (ds *DatabaseStore, err error) { } // initializeConfigurationsTable ensures the requisite tables in place to form the backing store. -// -// Uses MEDIUMTEXT on MySQL, and TEXT on sane databases. func (ds *DatabaseStore) initializeConfigurationsTable() error { assetsList, err := assets.ReadDir(filepath.Join("migrations", ds.driverName)) if err != nil { @@ -132,18 +130,9 @@ func (ds *DatabaseStore) initializeConfigurationsTable() error { return engine.ApplyAll() } -// parseDSN splits up a connection string into a driver name and data source name. -// -// For example: -// -// mysql://mmuser:mostest@localhost:5432/mattermost_test -// -// returns -// -// driverName = mysql -// dataSourceName = mmuser:mostest@localhost:5432/mattermost_test +// parseDSN parses a PostgreSQL connection string and validates the scheme. // -// By contrast, a Postgres DSN is returned unmodified. +// Accepts postgres:// or postgresql:// schemes and returns the DSN unmodified. func parseDSN(dsn string) (string, string, error) { // Treat the DSN as the URL that it is. s := strings.SplitN(dsn, "://", 2) diff --git a/server/config/database_test.go b/server/config/database_test.go index 7fb8532d09e..34356a87cca 100644 --- a/server/config/database_test.go +++ b/server/config/database_test.go @@ -209,7 +209,7 @@ func TestDatabaseStoreNew(t *testing.T) { _, err := NewDatabaseStore("") require.Error(t, err) - _, err = NewDatabaseStore("mysql") + _, err = NewDatabaseStore("postgres") require.Error(t, err) }) @@ -1054,17 +1054,10 @@ func TestDatabaseStoreString(t *testing.T) { require.NotNil(t, ds) defer ds.Close() - if *mainHelper.GetSQLSettings().DriverName == "postgres" { - maskedDSN := ds.String() - assert.True(t, strings.HasPrefix(maskedDSN, "postgres://")) - assert.False(t, strings.Contains(maskedDSN, "mmuser")) - assert.False(t, strings.Contains(maskedDSN, "mostest")) - } else { - maskedDSN := ds.String() - assert.False(t, strings.HasPrefix(maskedDSN, "mysql://")) - assert.False(t, strings.Contains(maskedDSN, "mmuser")) - assert.False(t, strings.Contains(maskedDSN, "mostest")) - } + maskedDSN := ds.String() + assert.True(t, strings.HasPrefix(maskedDSN, "postgres://")) + assert.False(t, strings.Contains(maskedDSN, "mmuser")) + assert.False(t, strings.Contains(maskedDSN, "mostest")) } func TestCleanUp(t *testing.T) { diff --git a/server/config/migrate_test.go b/server/config/migrate_test.go index 3941914a4a3..2e55f09d3c6 100644 --- a/server/config/migrate_test.go +++ b/server/config/migrate_test.go @@ -64,10 +64,10 @@ func TestMigrate(t *testing.T) { files[4], } cfg.SqlSettings.DataSourceReplicas = []string{ - "mysql://mmuser:password@tcp(replicahost:3306)/mattermost", + "postgres://mmuser:password@replicahost:5432/mattermost", } cfg.SqlSettings.DataSourceSearchReplicas = []string{ - "mysql://mmuser:password@tcp(searchreplicahost:3306)/mattermost", + "postgres://mmuser:password@searchreplicahost:5432/mattermost", } _, _, err := source.Set(cfg) diff --git a/server/config/utils.go b/server/config/utils.go index cb6b645abc6..2a104522b8f 100644 --- a/server/config/utils.go +++ b/server/config/utils.go @@ -169,8 +169,7 @@ func Merge(cfg *model.Config, patch *model.Config, mergeConfig *utils.MergeConfi } func IsDatabaseDSN(dsn string) bool { - return strings.HasPrefix(dsn, "mysql://") || - strings.HasPrefix(dsn, "postgres://") || + return strings.HasPrefix(dsn, "postgres://") || strings.HasPrefix(dsn, "postgresql://") } diff --git a/server/config/utils_test.go b/server/config/utils_test.go index dbd6a0ede14..2e676b3b509 100644 --- a/server/config/utils_test.go +++ b/server/config/utils_test.go @@ -168,11 +168,6 @@ func TestIsDatabaseDSN(t *testing.T) { DSN string Expected bool }{ - { - Name: "Mysql DSN", - DSN: "mysql://localhost", - Expected: true, - }, { Name: "Postgresql 'postgres' DSN", DSN: "postgres://localhost", @@ -231,7 +226,6 @@ func TestIsJSONMap(t *testing.T) { {name: "array json", data: `["test1", "test2"]`, want: false}, {name: "bad json", data: `{huh?}`, want: false}, {name: "filename", data: "/tmp/logger.conf", want: false}, - {name: "mysql dsn", data: "mysql://mmuser:@tcp(localhost:3306)/mattermost?charset=utf8mb4,utf8&readTimeout=30s", want: false}, {name: "postgres dsn", data: "postgres://mmuser:passwordlocalhost:5432/mattermost?sslmode=disable&connect_timeout=10", want: false}, } for _, tt := range tests { diff --git a/server/public/model/config.go b/server/public/model/config.go index 77aa65e6596..bfc42f8156a 100644 --- a/server/public/model/config.go +++ b/server/public/model/config.go @@ -5061,49 +5061,39 @@ func (o *Config) Sanitize(pluginManifests []*Manifest, opts *SanitizeOptions) { o.PluginSettings.Sanitize(pluginManifests) } -// SanitizeDataSource redacts sensitive information (username and password) from a database +// SanitizeDataSource redacts sensitive information (username and password) from a PostgreSQL // connection string while preserving other connection parameters. // -// Parameters: -// - driverName: The database driver name (postgres or mysql) -// - dataSource: The database connection string to sanitize -// -// Returns: -// - The sanitized connection string with username/password replaced by SanitizedPassword -// - An error if the driverName is not supported or if parsing fails +// Example: // -// Examples: -// - PostgreSQL: "postgres://user:pass@host:5432/db" -> "postgres://****:****@host:5432/db" -// - MySQL: "user:pass@tcp(host:3306)/db" -> "****:****@tcp(host:3306)/db" +// "postgres://user:pass@host:5432/db" -> "postgres://****:****@host:5432/db" func SanitizeDataSource(driverName, dataSource string) (string, error) { - // Handle empty data source if dataSource == "" { return "", nil } - switch driverName { - case DatabaseDriverPostgres: - u, err := url.Parse(dataSource) - if err != nil { - return "", err - } - u.User = url.UserPassword(SanitizedPassword, SanitizedPassword) + if driverName != DatabaseDriverPostgres { + return "", errors.New("invalid drivername: only postgres is supported") + } - // Remove username and password from query string - params := u.Query() - params.Del("user") - params.Del("password") - u.RawQuery = params.Encode() + u, err := url.Parse(dataSource) + if err != nil { + return "", err + } + u.User = url.UserPassword(SanitizedPassword, SanitizedPassword) - // Unescape the URL to make it human-readable - out, err := url.QueryUnescape(u.String()) - if err != nil { - return "", err - } - return out, nil - default: - return "", errors.New("invalid drivername. Not postgres or mysql.") + // Remove username and password from query string + params := u.Query() + params.Del("user") + params.Del("password") + u.RawQuery = params.Encode() + + // Unescape the URL to make it human-readable + out, err := url.QueryUnescape(u.String()) + if err != nil { + return "", err } + return out, nil } type FilterTag struct { diff --git a/server/public/model/config_test.go b/server/public/model/config_test.go index 677b2d6c809..84b10030bdd 100644 --- a/server/public/model/config_test.go +++ b/server/public/model/config_test.go @@ -2525,7 +2525,7 @@ func TestFilterConfig(t *testing.T) { require.NoError(t, err) require.Empty(t, m) - cfg.SqlSettings.DriverName = NewPointer("mysql") + cfg.SqlSettings.DriverName = NewPointer("postgresql") m, err = FilterConfig(cfg, ConfigFilterOptions{ GetConfigOptions: GetConfigOptions{ RemoveDefaults: true, @@ -2534,7 +2534,7 @@ func TestFilterConfig(t *testing.T) { }) require.NoError(t, err) require.NotEmpty(t, m) - require.Equal(t, "mysql", m["SqlSettings"].(map[string]any)["DriverName"]) + require.Equal(t, "postgresql", m["SqlSettings"].(map[string]any)["DriverName"]) }) t.Run("should not clear non primitive types", func(t *testing.T) { diff --git a/server/public/model/file_info.go b/server/public/model/file_info.go index 7be518c9942..d334246fab6 100644 --- a/server/public/model/file_info.go +++ b/server/public/model/file_info.go @@ -53,7 +53,7 @@ type FileInfo struct { Width int `json:"width,omitempty"` Height int `json:"height,omitempty"` HasPreviewImage bool `json:"has_preview_image,omitempty"` - MiniPreview *[]byte `json:"mini_preview"` // declared as *[]byte to avoid postgres/mysql differences in deserialization + MiniPreview *[]byte `json:"mini_preview"` // pointer to distinguish NULL (no preview) from empty data Content string `json:"-"` RemoteId *string `json:"remote_id"` Archived bool `json:"archived"` diff --git a/server/public/model/link_metadata.go b/server/public/model/link_metadata.go index 4c53784e20c..7055e9845e0 100644 --- a/server/public/model/link_metadata.go +++ b/server/public/model/link_metadata.go @@ -136,10 +136,8 @@ func (o *LinkMetadata) DeserializeDataToConcreteType() error { var b []byte switch t := o.Data.(type) { case []byte: - // MySQL uses a byte slice for JSON b = t case string: - // Postgres uses a string for JSON b = []byte(t) } diff --git a/server/public/model/post.go b/server/public/model/post.go index 654492c80ab..1b16b170292 100644 --- a/server/public/model/post.go +++ b/server/public/model/post.go @@ -64,7 +64,7 @@ const ( PostFilenamesMaxRunes = 4000 PostHashtagsMaxRunes = 1000 PostMessageMaxRunesV1 = 4000 - PostMessageMaxBytesV2 = 65535 // Maximum size of a TEXT column in MySQL + PostMessageMaxBytesV2 = 65535 PostMessageMaxRunesV2 = PostMessageMaxBytesV2 / 4 // Assume a worst-case representation // Reporting API constants diff --git a/server/public/plugin/driver.go b/server/public/plugin/driver.go index ba5c5d9aca4..ea420739fa3 100644 --- a/server/public/plugin/driver.go +++ b/server/public/plugin/driver.go @@ -54,9 +54,7 @@ type Driver interface { // TODO: add this // RowsColumnScanType(rowsID string, index int) reflect.Type - // Note: the following cannot be implemented because either MySQL or PG - // does not support it. So this implementation has to be a common subset - // of both DB implementations. + // Note: the following are not currently implemented. // RowsColumnTypeLength(rowsID string, index int) (int64, bool) // RowsColumnTypeNullable(rowsID string, index int) (bool, bool) // ResetSession(ctx context.Context) error diff --git a/server/scripts/esrupgrades/esr.5.37-6.3.mysql.cleanup.sql b/server/scripts/esrupgrades/esr.5.37-6.3.mysql.cleanup.sql deleted file mode 100644 index 3a13b11f83a..00000000000 --- a/server/scripts/esrupgrades/esr.5.37-6.3.mysql.cleanup.sql +++ /dev/null @@ -1,160 +0,0 @@ -/* Product notices are controlled externally, via the mattermost/notices repository. - When there is a new notice specified there, the server may have time, right after - the migration and before it is shut down, to download it and modify the - ProductNoticeViewState table, adding a row for all users that have not seen it or - removing old notices that no longer need to be shown. This can happen in the - UpdateProductNotices function that is executed periodically to update the notices - cache. The script will never do this, so we need to remove all rows in that table - to avoid any unwanted diff. */ -DELETE FROM ProductNoticeViewState; - -/* The script does not update the Systems row that tracks the version, so it is manually updated - here so that it does not show in the diff. */ -UPDATE Systems SET Value = '6.3.0' WHERE Name = 'Version'; - -/* The script does not update the schema_migrations table, which is automatically used by the - migrate library to track the version, so we drop it altogether to avoid spurious errors in - the diff */ -DROP TABLE IF EXISTS schema_migrations; - -/* Migration 000054_create_crt_channelmembership_count.up sets - ChannelMembers.LastUpdateAt to the results of SELECT ROUND(UNIX_TIMESTAMP(NOW(3))*1000) - which will be different each time the migration is run. Thus, the column will always be - different when comparing the server and script migrations. To bypass this, we update all - rows in ChannelMembers so that they contain the same value for such column. */ -UPDATE ChannelMembers SET LastUpdateAt = 1; - -/* Migration 000055_create_crt_thread_count_and_unreads.up sets - ThreadMemberships.LastUpdated to the results of SELECT ROUND(UNIX_TIMESTAMP(NOW(3))*1000) - which will be different each time the migration is run. Thus, the column will always be - different when comparing the server and script migrations. To bypass this, we update all - rows in ThreadMemberships so that they contain the same value for such column. */ -UPDATE ThreadMemberships SET LastUpdated = 1; - -/* The security update check in the server may update the LastSecurityTime system value. To - avoid any spurious difference in the migrations, we update it to a fixed value. */ -UPDATE Systems SET Value = 1 WHERE Name = 'LastSecurityTime'; - -/* The server migration contains an in-app migration that adds new roles for Playbooks: - doPlaybooksRolesCreationMigration, defined in https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/app/migrations.go#L345-L469 - The roles are the ones defined in https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/model/role.go#L874-L929 - When this migration finishes, it also adds a new row to the Systems table with the key of the migration. - This in-app migration does not happen in the script, so we remove those rows here. */ -DELETE FROM Roles WHERE Name = 'playbook_member'; -DELETE FROM Roles WHERE Name = 'playbook_admin'; -DELETE FROM Roles WHERE Name = 'run_member'; -DELETE FROM Roles WHERE Name = 'run_admin'; -DELETE FROM Systems WHERE Name = 'PlaybookRolesCreationMigrationComplete'; - -/* The server migration contains an in-app migration that add playbooks permissions to certain roles: - getAddPlaybooksPermissions, defined in https://github.com/mattermost/mattermost-server/blob/f9b996934cabf9a8fad5901835e7e9b418917402/app/permissions_migrations.go#L918-L951 - The specific roles ('%playbook%') are removed in the procedure below, but the migrations also add a new row to the Systems table marking the migration as complete. - This in-app migration does not happen in the script, so we remove that rows here. */ -DELETE FROM Systems WHERE Name = 'playbooks_permissions'; - -/* The rest of this script defines and executes a procedure to update the Roles table. It performs several changes: - 1. Set the UpdateAt column of all rows to a fixed value, so that the server migration changes to this column - do not appear in the diff. - 2. Remove the set of specific permissions added in the server migration that is not covered by the script, as - this logic happens all in-app after the normal DB migrations. - 3. Set a consistent order in the Permissions column, which is modelled a space-separated string containing each of - the different permissions each role has. This change is the reason why we need a complex procedure, which creates - a temporary table that pairs each single permission to its corresponding ID. So if the Roles table contains two - rows like: - Id: 'abcd' - Permissions: 'view_team read_public_channel invite_user' - Id: 'efgh' - Permissions: 'view_team create_emojis' - then the new temporary table will contain five rows like: - Id: 'abcd' - Permissions: 'view_team' - Id: 'abcd' - Permissions: 'read_public_channel' - Id: 'abcd' - Permissions: 'invite_user' - Id: 'efgh' - Permissions: 'view_team' - Id: 'efgh' - Permissions: 'create_emojis' -*/ - -DROP PROCEDURE IF EXISTS splitPermissions; -DROP PROCEDURE IF EXISTS sortAndFilterPermissionsInRoles; - -DROP TEMPORARY TABLE IF EXISTS temp_roles; -CREATE TEMPORARY TABLE temp_roles(id varchar(26), permission longtext); - -DELIMITER // - -/* Auxiliary procedure that splits the space-separated permissions string into single rows that are inserted - in the temporary temp_roles table along with their corresponding ID. */ -CREATE PROCEDURE splitPermissions( - IN id varchar(26), - IN permissionsString longtext -) -BEGIN - DECLARE idx INT DEFAULT 0; - SELECT TRIM(permissionsString) INTO permissionsString; - SELECT LOCATE(' ', permissionsString) INTO idx; - WHILE idx > 0 DO - INSERT INTO temp_roles SELECT id, TRIM(LEFT(permissionsString, idx)); - SELECT SUBSTR(permissionsString, idx+1) INTO permissionsString; - SELECT LOCATE(' ', permissionsString) INTO idx; - END WHILE; - INSERT INTO temp_roles(id, permission) VALUES(id, TRIM(permissionsString)); -END; // - -/* Main procedure that does update the Roles table */ -CREATE PROCEDURE sortAndFilterPermissionsInRoles() -BEGIN - DECLARE done INT DEFAULT FALSE; - DECLARE rolesId varchar(26) DEFAULT ''; - DECLARE rolesPermissions longtext DEFAULT ''; - DECLARE cur1 CURSOR FOR SELECT Id, Permissions FROM Roles; - DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; - - /* 1. Set a fixed value in the UpdateAt column for all rows in Roles table */ - UPDATE Roles SET UpdateAt = 1; - - /* Call splitPermissions for every row in the Roles table, thus populating the - temp_roles table. */ - OPEN cur1; - read_loop: LOOP - FETCH cur1 INTO rolesId, rolesPermissions; - IF done THEN - LEAVE read_loop; - END IF; - CALL splitPermissions(rolesId, rolesPermissions); - END LOOP; - CLOSE cur1; - - /* 2. Filter out the new permissions added by the in-app migrations */ - DELETE FROM temp_roles WHERE permission LIKE '%playbook%'; - DELETE FROM temp_roles WHERE permission LIKE 'run_create'; - DELETE FROM temp_roles WHERE permission LIKE 'run_manage_members'; - DELETE FROM temp_roles WHERE permission LIKE 'run_manage_properties'; - DELETE FROM temp_roles WHERE permission LIKE 'run_view'; - - /* Temporarily set to the maximum permitted value, since the call to group_concat - below needs a value bigger than the default */ - SET group_concat_max_len = 18446744073709551615; - - /* 3. Update the Permissions column in the Roles table with the filtered, sorted permissions, - concatenated again as a space-separated string */ - UPDATE - Roles INNER JOIN ( - SELECT temp_roles.id as Id, TRIM(group_concat(temp_roles.permission ORDER BY temp_roles.permission SEPARATOR ' ')) as Permissions - FROM Roles JOIN temp_roles ON Roles.Id = temp_roles.id - GROUP BY temp_roles.id - ) AS Sorted - ON Roles.Id = Sorted.Id - SET Roles.Permissions = Sorted.Permissions; - - /* Reset group_concat_max_len to its default value */ - SET group_concat_max_len = 1024; -END; // -DELIMITER ; - -CALL sortAndFilterPermissionsInRoles(); - -DROP TEMPORARY TABLE IF EXISTS temp_roles; diff --git a/server/scripts/esrupgrades/esr.5.37-6.3.mysql.up.sql b/server/scripts/esrupgrades/esr.5.37-6.3.mysql.up.sql deleted file mode 100644 index 53c1c211fab..00000000000 --- a/server/scripts/esrupgrades/esr.5.37-6.3.mysql.up.sql +++ /dev/null @@ -1,695 +0,0 @@ -/* ==> mysql/000054_create_crt_channelmembership_count.up.sql <== */ -/* fixCRTChannelMembershipCounts fixes the channel counts, i.e. the total message count, -total root message count, mention count, and mention count in root messages for users -who have viewed the channel after the last post in the channel */ - -DELIMITER // -CREATE PROCEDURE MigrateCRTChannelMembershipCounts () -BEGIN - IF( - SELECT - EXISTS ( - SELECT - * FROM Systems - WHERE - Name = 'CRTChannelMembershipCountsMigrationComplete') = 0) THEN - UPDATE - ChannelMembers - INNER JOIN Channels ON Channels.Id = ChannelMembers.ChannelId SET - MentionCount = 0, MentionCountRoot = 0, MsgCount = Channels.TotalMsgCount, MsgCountRoot = Channels.TotalMsgCountRoot, LastUpdateAt = ( - SELECT - (SELECT ROUND(UNIX_TIMESTAMP(NOW(3))*1000))) - WHERE - ChannelMembers.LastViewedAt >= Channels.LastPostAt; - INSERT INTO Systems - VALUES('CRTChannelMembershipCountsMigrationComplete', 'true'); - END IF; -END// -DELIMITER ; -CALL MigrateCRTChannelMembershipCounts (); -DROP PROCEDURE IF EXISTS MigrateCRTChannelMembershipCounts; - -/* ==> mysql/000055_create_crt_thread_count_and_unreads.up.sql <== */ -/* fixCRTThreadCountsAndUnreads Marks threads as read for users where the last -reply time of the thread is earlier than the time the user viewed the channel. -Marking a thread means setting the mention count to zero and setting the -last viewed at time of the the thread as the last viewed at time -of the channel */ - -DELIMITER // -CREATE PROCEDURE MigrateCRTThreadCountsAndUnreads () -BEGIN - IF(SELECT EXISTS(SELECT * FROM Systems WHERE Name = 'CRTThreadCountsAndUnreadsMigrationComplete') = 0) THEN - UPDATE - ThreadMemberships - INNER JOIN ( - SELECT - PostId, - UserId, - ChannelMembers.LastViewedAt AS CM_LastViewedAt, - Threads.LastReplyAt - FROM - Threads - INNER JOIN ChannelMembers ON ChannelMembers.ChannelId = Threads.ChannelId - WHERE - Threads.LastReplyAt <= ChannelMembers.LastViewedAt) AS q ON ThreadMemberships.Postid = q.PostId - AND ThreadMemberships.UserId = q.UserId SET LastViewed = q.CM_LastViewedAt + 1, UnreadMentions = 0, LastUpdated = ( - SELECT - (SELECT ROUND(UNIX_TIMESTAMP(NOW(3))*1000))); - INSERT INTO Systems - VALUES('CRTThreadCountsAndUnreadsMigrationComplete', 'true'); - END IF; -END// -DELIMITER ; -CALL MigrateCRTThreadCountsAndUnreads (); -DROP PROCEDURE IF EXISTS MigrateCRTThreadCountsAndUnreads; - -/* ==> mysql/000056_upgrade_channels_v6.0.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Channels' - AND table_schema = DATABASE() - AND index_name = 'idx_channels_team_id_display_name' - ) > 0, - 'SELECT 1', - 'CREATE INDEX idx_channels_team_id_display_name ON Channels(TeamId, DisplayName);' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Channels' - AND table_schema = DATABASE() - AND index_name = 'idx_channels_team_id_type' - ) > 0, - 'SELECT 1', - 'CREATE INDEX idx_channels_team_id_type ON Channels(TeamId, Type);' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Channels' - AND table_schema = DATABASE() - AND index_name = 'idx_channels_team_id' - ) > 0, - 'DROP INDEX idx_channels_team_id ON Channels;', - 'SELECT 1' -)); - -PREPARE removeIndexIfExists FROM @preparedStatement; -EXECUTE removeIndexIfExists; -DEALLOCATE PREPARE removeIndexIfExists; - -/* ==> mysql/000057_upgrade_command_webhooks_v6.0.up.sql <== */ - -DELIMITER // -CREATE PROCEDURE MigrateRootId_CommandWebhooks () BEGIN DECLARE ParentId_EXIST INT; -SELECT COUNT(*) -FROM INFORMATION_SCHEMA.COLUMNS -WHERE TABLE_NAME = 'CommandWebhooks' - AND table_schema = DATABASE() - AND COLUMN_NAME = 'ParentId' INTO ParentId_EXIST; -IF(ParentId_EXIST > 0) THEN - UPDATE CommandWebhooks SET RootId = ParentId WHERE RootId = '' AND RootId != ParentId; -END IF; -END// -DELIMITER ; -CALL MigrateRootId_CommandWebhooks (); -DROP PROCEDURE IF EXISTS MigrateRootId_CommandWebhooks; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'CommandWebhooks' - AND table_schema = DATABASE() - AND column_name = 'ParentId' - ) > 0, - 'ALTER TABLE CommandWebhooks DROP COLUMN ParentId;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -/* ==> mysql/000058_upgrade_channelmembers_v6.0.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'ChannelMembers' - AND table_schema = DATABASE() - AND column_name = 'NotifyProps' - AND column_type != 'JSON' - ) > 0, - 'ALTER TABLE ChannelMembers MODIFY COLUMN NotifyProps JSON;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'ChannelMembers' - AND table_schema = DATABASE() - AND index_name = 'idx_channelmembers_user_id' - ) > 0, - 'DROP INDEX idx_channelmembers_user_id ON ChannelMembers;', - 'SELECT 1' -)); - -PREPARE removeIndexIfExists FROM @preparedStatement; -EXECUTE removeIndexIfExists; -DEALLOCATE PREPARE removeIndexIfExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'ChannelMembers' - AND table_schema = DATABASE() - AND index_name = 'idx_channelmembers_user_id_channel_id_last_viewed_at' - ) > 0, - 'SELECT 1', - 'CREATE INDEX idx_channelmembers_user_id_channel_id_last_viewed_at ON ChannelMembers(UserId, ChannelId, LastViewedAt);' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'ChannelMembers' - AND table_schema = DATABASE() - AND index_name = 'idx_channelmembers_channel_id_scheme_guest_user_id' - ) > 0, - 'SELECT 1', - 'CREATE INDEX idx_channelmembers_channel_id_scheme_guest_user_id ON ChannelMembers(ChannelId, SchemeGuest, UserId);' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; - -/* ==> mysql/000059_upgrade_users_v6.0.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'Props' - AND column_type != 'JSON' - ) > 0, - 'ALTER TABLE Users MODIFY COLUMN Props JSON;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'NotifyProps' - AND column_type != 'JSON' - ) > 0, - 'ALTER TABLE Users MODIFY COLUMN NotifyProps JSON;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'Timezone' - AND column_default IS NOT NULL - ) > 0, - 'ALTER TABLE Users ALTER Timezone DROP DEFAULT;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'Timezone' - AND column_type != 'JSON' - ) > 0, - 'ALTER TABLE Users MODIFY COLUMN Timezone JSON;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'Roles' - AND column_type != 'text' - ) > 0, - 'ALTER TABLE Users MODIFY COLUMN Roles text;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -/* ==> mysql/000060_upgrade_jobs_v6.0.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Jobs' - AND table_schema = DATABASE() - AND column_name = 'Data' - AND column_type != 'JSON' - ) > 0, - 'ALTER TABLE Jobs MODIFY COLUMN Data JSON;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - - -/* ==> mysql/000061_upgrade_link_metadata_v6.0.up.sql <== */ - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'LinkMetadata' - AND table_schema = DATABASE() - AND column_name = 'Data' - AND column_type != 'JSON' - ) > 0, - 'ALTER TABLE LinkMetadata MODIFY COLUMN Data JSON;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -/* ==> mysql/000062_upgrade_sessions_v6.0.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Sessions' - AND table_schema = DATABASE() - AND column_name = 'Props' - AND column_type != 'JSON' - ) > 0, - 'ALTER TABLE Sessions MODIFY COLUMN Props JSON;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - - -/* ==> mysql/000063_upgrade_threads_v6.0.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Threads' - AND table_schema = DATABASE() - AND column_name = 'Participants' - AND column_type != 'JSON' - ) > 0, - 'ALTER TABLE Threads MODIFY COLUMN Participants JSON;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Threads' - AND table_schema = DATABASE() - AND index_name = 'idx_threads_channel_id_last_reply_at' - ) > 0, - 'SELECT 1', - 'CREATE INDEX idx_threads_channel_id_last_reply_at ON Threads(ChannelId, LastReplyAt);' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Threads' - AND table_schema = DATABASE() - AND index_name = 'idx_threads_channel_id' - ) > 0, - 'DROP INDEX idx_threads_channel_id ON Threads;', - 'SELECT 1' -)); - -PREPARE removeIndexIfExists FROM @preparedStatement; -EXECUTE removeIndexIfExists; -DEALLOCATE PREPARE removeIndexIfExists; - -/* ==> mysql/000064_upgrade_status_v6.0.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Status' - AND table_schema = DATABASE() - AND index_name = 'idx_status_status_dndendtime' - ) > 0, - 'SELECT 1', - 'CREATE INDEX idx_status_status_dndendtime ON Status(Status, DNDEndTime);' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Status' - AND table_schema = DATABASE() - AND index_name = 'idx_status_status' - ) > 0, - 'DROP INDEX idx_status_status ON Status;', - 'SELECT 1' -)); - -PREPARE removeIndexIfExists FROM @preparedStatement; -EXECUTE removeIndexIfExists; -DEALLOCATE PREPARE removeIndexIfExists; - -/* ==> mysql/000065_upgrade_groupchannels_v6.0.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'GroupChannels' - AND table_schema = DATABASE() - AND index_name = 'idx_groupchannels_schemeadmin' - ) > 0, - 'SELECT 1', - 'CREATE INDEX idx_groupchannels_schemeadmin ON GroupChannels(SchemeAdmin);' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; - -/* ==> mysql/000066_upgrade_posts_v6.0.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateRootId_Posts () -BEGIN -DECLARE ParentId_EXIST INT; -DECLARE Alter_FileIds INT; -DECLARE Alter_Props INT; -SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS -WHERE TABLE_NAME = 'Posts' - AND table_schema = DATABASE() - AND COLUMN_NAME = 'ParentId' INTO ParentId_EXIST; -SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Posts' - AND table_schema = DATABASE() - AND column_name = 'FileIds' - AND column_type != 'text' INTO Alter_FileIds; -SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Posts' - AND table_schema = DATABASE() - AND column_name = 'Props' - AND column_type != 'JSON' INTO Alter_Props; -IF (Alter_Props OR Alter_FileIds) THEN - IF(ParentId_EXIST > 0) THEN - UPDATE Posts SET RootId = ParentId WHERE RootId = '' AND RootId != ParentId; - ALTER TABLE Posts MODIFY COLUMN FileIds text, MODIFY COLUMN Props JSON, DROP COLUMN ParentId; - ELSE - ALTER TABLE Posts MODIFY COLUMN FileIds text, MODIFY COLUMN Props JSON; - END IF; -END IF; -END// -DELIMITER ; -CALL MigrateRootId_Posts (); -DROP PROCEDURE IF EXISTS MigrateRootId_Posts; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Posts' - AND table_schema = DATABASE() - AND index_name = 'idx_posts_root_id_delete_at' - ) > 0, - 'SELECT 1', - 'CREATE INDEX idx_posts_root_id_delete_at ON Posts(RootId, DeleteAt);' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Posts' - AND table_schema = DATABASE() - AND index_name = 'idx_posts_root_id' - ) > 0, - 'DROP INDEX idx_posts_root_id ON Posts;', - 'SELECT 1' -)); - -PREPARE removeIndexIfExists FROM @preparedStatement; -EXECUTE removeIndexIfExists; -DEALLOCATE PREPARE removeIndexIfExists; - -/* ==> mysql/000067_upgrade_channelmembers_v6.1.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'ChannelMembers' - AND table_schema = DATABASE() - AND column_name = 'Roles' - AND column_type != 'text' - ) > 0, - 'ALTER TABLE ChannelMembers MODIFY COLUMN Roles text;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -/* ==> mysql/000068_upgrade_teammembers_v6.1.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'TeamMembers' - AND table_schema = DATABASE() - AND column_name = 'Roles' - AND column_type != 'text' - ) > 0, - 'ALTER TABLE TeamMembers MODIFY COLUMN Roles text;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -/* ==> mysql/000069_upgrade_jobs_v6.1.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Jobs' - AND table_schema = DATABASE() - AND index_name = 'idx_jobs_status_type' - ) > 0, - 'SELECT 1', - 'CREATE INDEX idx_jobs_status_type ON Jobs(Status, Type);' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; - -/* ==> mysql/000070_upgrade_cte_v6.1.up.sql <== */ -DELIMITER // -CREATE PROCEDURE Migrate_LastRootPostAt () -BEGIN -DECLARE - LastRootPostAt_EXIST INT; - SELECT - COUNT(*) - FROM - INFORMATION_SCHEMA.COLUMNS - WHERE - TABLE_NAME = 'Channels' - AND table_schema = DATABASE() - AND COLUMN_NAME = 'LastRootPostAt' INTO LastRootPostAt_EXIST; - IF(LastRootPostAt_EXIST = 0) THEN - ALTER TABLE Channels ADD COLUMN LastRootPostAt bigint DEFAULT 0; - UPDATE - Channels - INNER JOIN ( - SELECT - Channels.Id channelid, - COALESCE(MAX(Posts.CreateAt), 0) AS lastrootpost - FROM - Channels - LEFT JOIN Posts FORCE INDEX (idx_posts_channel_id_update_at) ON Channels.Id = Posts.ChannelId - WHERE - Posts.RootId = '' - GROUP BY - Channels.Id) AS q ON q.channelid = Channels.Id SET LastRootPostAt = lastrootpost; - END IF; -END// -DELIMITER ; -CALL Migrate_LastRootPostAt (); -DROP PROCEDURE IF EXISTS Migrate_LastRootPostAt; - -/* ==> mysql/000071_upgrade_sessions_v6.1.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Sessions' - AND table_schema = DATABASE() - AND column_name = 'Roles' - AND column_type != 'text' - ) > 0, - 'ALTER TABLE Sessions MODIFY COLUMN Roles text;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -/* ==> mysql/000072_upgrade_schemes_v6.3.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Schemes' - AND table_schema = DATABASE() - AND column_name = 'DefaultPlaybookAdminRole' - ) > 0, - 'SELECT 1', - 'ALTER TABLE Schemes ADD COLUMN DefaultPlaybookAdminRole VARCHAR(64) DEFAULT "";' -)); - -PREPARE alterIfNotExists FROM @preparedStatement; -EXECUTE alterIfNotExists; -DEALLOCATE PREPARE alterIfNotExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Schemes' - AND table_schema = DATABASE() - AND column_name = 'DefaultPlaybookMemberRole' - ) > 0, - 'SELECT 1', - 'ALTER TABLE Schemes ADD COLUMN DefaultPlaybookMemberRole VARCHAR(64) DEFAULT "";' -)); - -PREPARE alterIfNotExists FROM @preparedStatement; -EXECUTE alterIfNotExists; -DEALLOCATE PREPARE alterIfNotExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Schemes' - AND table_schema = DATABASE() - AND column_name = 'DefaultRunAdminRole' - ) > 0, - 'SELECT 1', - 'ALTER TABLE Schemes ADD COLUMN DefaultRunAdminRole VARCHAR(64) DEFAULT "";' -)); - -PREPARE alterIfNotExists FROM @preparedStatement; -EXECUTE alterIfNotExists; -DEALLOCATE PREPARE alterIfNotExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Schemes' - AND table_schema = DATABASE() - AND column_name = 'DefaultRunMemberRole' - ) > 0, - 'SELECT 1', - 'ALTER TABLE Schemes ADD COLUMN DefaultRunMemberRole VARCHAR(64) DEFAULT "";' -)); - -PREPARE alterIfNotExists FROM @preparedStatement; -EXECUTE alterIfNotExists; -DEALLOCATE PREPARE alterIfNotExists; - -/* ==> mysql/000073_upgrade_plugin_key_value_store_v6.3.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT Count(*) FROM Information_Schema.Columns - WHERE table_name = 'PluginKeyValueStore' - AND table_schema = DATABASE() - AND column_name = 'PKey' - AND column_type != 'varchar(150)' - ) > 0, - 'ALTER TABLE PluginKeyValueStore MODIFY COLUMN PKey varchar(150);', - 'SELECT 1' -)); - -PREPARE alterTypeIfExists FROM @preparedStatement; -EXECUTE alterTypeIfExists; -DEALLOCATE PREPARE alterTypeIfExists; - -/* ==> mysql/000074_upgrade_users_v6.3.up.sql <== */ - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'AcceptedTermsOfServiceId' - ) > 0, - 'ALTER TABLE Users DROP COLUMN AcceptedTermsOfServiceId;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; diff --git a/server/scripts/esrupgrades/esr.5.37-7.8.mysql.cleanup.sql b/server/scripts/esrupgrades/esr.5.37-7.8.mysql.cleanup.sql deleted file mode 100644 index 4c23874cb12..00000000000 --- a/server/scripts/esrupgrades/esr.5.37-7.8.mysql.cleanup.sql +++ /dev/null @@ -1,199 +0,0 @@ -/* Product notices are controlled externally, via the mattermost/notices repository. - When there is a new notice specified there, the server may have time, right after - the migration and before it is shut down, to download it and modify the - ProductNoticeViewState table, adding a row for all users that have not seen it or - removing old notices that no longer need to be shown. This can happen in the - UpdateProductNotices function that is executed periodically to update the notices - cache. The script will never do this, so we need to remove all rows in that table - to avoid any unwanted diff. */ -DELETE FROM ProductNoticeViewState; - -/* Remove migration-related tables that are only updated through the server to track which - migrations have been applied */ -DROP TABLE IF EXISTS db_lock; -DROP TABLE IF EXISTS db_migrations; - -/* Migration 000054_create_crt_channelmembership_count.up sets - ChannelMembers.LastUpdateAt to the results of SELECT ROUND(UNIX_TIMESTAMP(NOW(3))*1000) - which will be different each time the migration is run. Thus, the column will always be - different when comparing the server and script migrations. To bypass this, we update all - rows in ChannelMembers so that they contain the same value for such column. */ -UPDATE ChannelMembers SET LastUpdateAt = 1; - -/* Migration 000055_create_crt_thread_count_and_unreads.up sets - ThreadMemberships.LastUpdated to the results of SELECT ROUND(UNIX_TIMESTAMP(NOW(3))*1000) - which will be different each time the migration is run. Thus, the column will always be - different when comparing the server and script migrations. To bypass this, we update all - rows in ThreadMemberships so that they contain the same value for such column. */ -UPDATE ThreadMemberships SET LastUpdated = 1; - -/* The security update check in the server may update the LastSecurityTime system value. To - avoid any spurious difference in the migrations, we update it to a fixed value. */ -UPDATE Systems SET Value = 1 WHERE Name = 'LastSecurityTime'; - -/* The server migration may contain a row in the Systems table marking the onboarding as complete. - There are no migrations related to this, so we can simply drop it here. */ -DELETE FROM Systems WHERE Name = 'FirstAdminSetupComplete'; - -/* The server migration contains an in-app migration that adds new roles for Playbooks: - doPlaybooksRolesCreationMigration, defined in https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/app/migrations.go#L345-L469 - The roles are the ones defined in https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/model/role.go#L874-L929 - When this migration finishes, it also adds a new row to the Systems table with the key of the migration. - This in-app migration does not happen in the script, so we remove those rows here. */ -DELETE FROM Roles WHERE Name = 'playbook_member'; -DELETE FROM Roles WHERE Name = 'playbook_admin'; -DELETE FROM Roles WHERE Name = 'run_member'; -DELETE FROM Roles WHERE Name = 'run_admin'; -DELETE FROM Systems WHERE Name = 'PlaybookRolesCreationMigrationComplete'; - -/* The server migration contains two in-app migrations that add playbooks permissions to certain roles: - getAddPlaybooksPermissions and getPlaybooksPermissionsAddManageRoles, defined in https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/app/permissions_migrations.go#L1021-L1072 - The specific roles ('%playbook%') are removed in the procedure below, but the migrations also add new rows to the Systems table marking the migrations as complete. - These in-app migrations do not happen in the script, so we remove those rows here. */ -DELETE FROM Systems WHERE Name = 'playbooks_manage_roles'; -DELETE FROM Systems WHERE Name = 'playbooks_permissions'; - -/* The server migration contains an in-app migration that adds boards permissions to certain roles: - getProductsBoardsPermissions, defined in https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/app/permissions_migrations.go#L1074-L1093 - The specific roles (sysconsole_read_product_boards and sysconsole_write_product_boards) are removed in the procedure below, - but the migrations also adds a new row to the Systems table marking the migrations as complete. - This in-app migration does not happen in the script, so we remove that row here. */ -DELETE FROM Systems WHERE Name = 'products_boards'; - -/* TODO: REVIEW STARTING HERE */ - -/* The server migration contain an in-app migration that adds Ids to the Teams whose InviteId is an empty string: - doRemainingSchemaMigrations, defined in https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/app/migrations.go#L515-L540 - The migration is not replicated in the script, since it happens in-app, but the server adds a new row to the - Systems table marking the table as complete, which the script doesn't do, so we remove that row here. */ -DELETE FROM Systems WHERE Name = 'RemainingSchemaMigrations'; - -/* The server migration contains three in-app migration that adds a new role and new permissions - related to custom groups. The migrations are: - - doCustomGroupAdminRoleCreationMigration https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/app/migrations.go#L345-L469 - - getAddCustomUserGroupsPermissions https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/app/permissions_migrations.go#L974-L995 - - getAddCustomUserGroupsPermissionRestore https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/app/permissions_migrations.go#L997-L1019 - The specific roles and permissions are removed in the procedure below, but the migrations also - adds a new row to the Roles table for the new role and new rows to the Systems table marking the - migrations as complete. - This in-app migration does not happen in the script, so we remove that row here. */ -DELETE FROM Roles WHERE Name = 'system_custom_group_admin'; -DELETE FROM Systems WHERE Name = 'CustomGroupAdminRoleCreationMigrationComplete'; -DELETE FROM Systems WHERE Name = 'custom_groups_permissions'; -DELETE FROM Systems WHERE Name = 'custom_groups_permission_restore'; - -/* The server migration contains an in-app migration that updates the config, setting ServiceSettings.PostPriority - to true, doPostPriorityConfigDefaultTrueMigration, defined in https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/app/migrations.go#L542-L560 - The migration is not replicated in the script, since it happens in-app, but the server adds a new row to the - Systems table marking the table as complete, which the script doesn't do, so we remove that row here. */ -DELETE FROM Systems WHERE Name = 'PostPriorityConfigDefaultTrueMigrationComplete'; - -/* The rest of this script defines and executes a procedure to update the Roles table. It performs several changes: - 1. Set the UpdateAt column of all rows to a fixed value, so that the server migration changes to this column - do not appear in the diff. - 2. Remove the set of specific permissions added in the server migration that is not covered by the script, as - this logic happens all in-app after the normal DB migrations. - 3. Set a consistent order in the Permissions column, which is modelled a space-separated string containing each of - the different permissions each role has. This change is the reason why we need a complex procedure, which creates - a temporary table that pairs each single permission to its corresponding ID. So if the Roles table contains two - rows like: - Id: 'abcd' - Permissions: 'view_team read_public_channel invite_user' - Id: 'efgh' - Permissions: 'view_team create_emojis' - then the new temporary table will contain five rows like: - Id: 'abcd' - Permissions: 'view_team' - Id: 'abcd' - Permissions: 'read_public_channel' - Id: 'abcd' - Permissions: 'invite_user' - Id: 'efgh' - Permissions: 'view_team' - Id: 'efgh' - Permissions: 'create_emojis' -*/ - -DROP PROCEDURE IF EXISTS splitPermissions; -DROP PROCEDURE IF EXISTS sortAndFilterPermissionsInRoles; - -DROP TEMPORARY TABLE IF EXISTS temp_roles; -CREATE TEMPORARY TABLE temp_roles(id varchar(26), permission longtext); - -DELIMITER // - -/* Auxiliary procedure that splits the space-separated permissions string into single rows that are inserted - in the temporary temp_roles table along with their corresponding ID. */ -CREATE PROCEDURE splitPermissions( - IN id varchar(26), - IN permissionsString longtext -) -BEGIN - DECLARE idx INT DEFAULT 0; - SELECT TRIM(permissionsString) INTO permissionsString; - SELECT LOCATE(' ', permissionsString) INTO idx; - WHILE idx > 0 DO - INSERT INTO temp_roles SELECT id, TRIM(LEFT(permissionsString, idx)); - SELECT SUBSTR(permissionsString, idx+1) INTO permissionsString; - SELECT LOCATE(' ', permissionsString) INTO idx; - END WHILE; - INSERT INTO temp_roles(id, permission) VALUES(id, TRIM(permissionsString)); -END; // - -/* Main procedure that does update the Roles table */ -CREATE PROCEDURE sortAndFilterPermissionsInRoles() -BEGIN - DECLARE done INT DEFAULT FALSE; - DECLARE rolesId varchar(26) DEFAULT ''; - DECLARE rolesPermissions longtext DEFAULT ''; - DECLARE cur1 CURSOR FOR SELECT Id, Permissions FROM Roles; - DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; - - /* 1. Set a fixed value in the UpdateAt column for all rows in Roles table */ - UPDATE Roles SET UpdateAt = 1; - - /* Call splitPermissions for every row in the Roles table, thus populating the - temp_roles table. */ - OPEN cur1; - read_loop: LOOP - FETCH cur1 INTO rolesId, rolesPermissions; - IF done THEN - LEAVE read_loop; - END IF; - CALL splitPermissions(rolesId, rolesPermissions); - END LOOP; - CLOSE cur1; - - /* 2. Filter out the new permissions added by the in-app migrations */ - DELETE FROM temp_roles WHERE permission LIKE 'sysconsole_read_products_boards'; - DELETE FROM temp_roles WHERE permission LIKE 'sysconsole_write_products_boards'; - DELETE FROM temp_roles WHERE permission LIKE '%playbook%'; - DELETE FROM temp_roles WHERE permission LIKE 'run_create'; - DELETE FROM temp_roles WHERE permission LIKE 'run_manage_members'; - DELETE FROM temp_roles WHERE permission LIKE 'run_manage_properties'; - DELETE FROM temp_roles WHERE permission LIKE 'run_view'; - DELETE FROM temp_roles WHERE permission LIKE '%custom_group%'; - - /* Temporarily set to the maximum permitted value, since the call to group_concat - below needs a value bigger than the default */ - SET group_concat_max_len = 18446744073709551615; - - /* 3. Update the Permissions column in the Roles table with the filtered, sorted permissions, - concatenated again as a space-separated string */ - UPDATE - Roles INNER JOIN ( - SELECT temp_roles.id as Id, TRIM(group_concat(temp_roles.permission ORDER BY temp_roles.permission SEPARATOR ' ')) as Permissions - FROM Roles JOIN temp_roles ON Roles.Id = temp_roles.id - GROUP BY temp_roles.id - ) AS Sorted - ON Roles.Id = Sorted.Id - SET Roles.Permissions = Sorted.Permissions; - - /* Reset group_concat_max_len to its default value */ - SET group_concat_max_len = 1024; -END; // -DELIMITER ; - -CALL sortAndFilterPermissionsInRoles(); - -DROP TEMPORARY TABLE IF EXISTS temp_roles; diff --git a/server/scripts/esrupgrades/esr.5.37-7.8.mysql.up.sql b/server/scripts/esrupgrades/esr.5.37-7.8.mysql.up.sql deleted file mode 100644 index 2c2d271351d..00000000000 --- a/server/scripts/esrupgrades/esr.5.37-7.8.mysql.up.sql +++ /dev/null @@ -1,1391 +0,0 @@ -/* ==> mysql/000041_create_upload_sessions.up.sql <== */ -/* Release 5.37 was meant to contain the index idx_uploadsessions_type, but a bug prevented that. - This part of the migration #41 adds such index */ -/* ==> mysql/000075_alter_upload_sessions_index.up.sql <== */ -/* ==> mysql/000090_create_enums.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateUploadSessions () -BEGIN - -- 'CREATE INDEX idx_uploadsessions_type ON UploadSessions(Type);' - DECLARE CreateIndex BOOLEAN; - DECLARE CreateIndexQuery TEXT DEFAULT NULL; - - -- 'DROP INDEX idx_uploadsessions_user_id ON UploadSessions; CREATE INDEX idx_uploadsessions_user_id ON UploadSessions(UserId);' - DECLARE AlterIndex BOOLEAN; - DECLARE AlterIndexQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE UploadSessions MODIFY COLUMN Type ENUM("attachment", "import");' - DECLARE AlterColumn BOOLEAN; - DECLARE AlterColumnQuery TEXT DEFAULT NULL; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'UploadSessions' - AND table_schema = DATABASE() - AND index_name = 'idx_uploadsessions_type' - INTO CreateIndex; - - SELECT IFNULL(GROUP_CONCAT(column_name ORDER BY seq_in_index), '') = 'Type' FROM information_schema.statistics - WHERE table_name = 'UploadSessions' - AND table_schema = DATABASE() - AND index_name = 'idx_uploadsessions_user_id' - GROUP BY index_name - INTO AlterIndex; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'UploadSessions' - AND table_schema = DATABASE() - AND column_name = 'Type' - AND REPLACE(LOWER(column_type), '"', "'") != "enum('attachment','import')" - INTO AlterColumn; - - IF CreateIndex THEN - SET CreateIndexQuery = 'ADD INDEX idx_uploadsessions_type (Type)'; - END IF; - - IF AlterIndex THEN - SET AlterIndexQuery = 'DROP INDEX idx_uploadsessions_user_id, ADD INDEX idx_uploadsessions_user_id (UserId)'; - END IF; - - IF AlterColumn THEN - SET AlterColumnQuery = 'MODIFY COLUMN Type ENUM("attachment", "import")'; - END IF; - - SET @alterQuery = CONCAT_WS(', ', CreateIndexQuery, AlterIndexQuery, AlterColumnQuery); - IF @alterQuery <> '' THEN - SET @query = CONCAT('ALTER TABLE UploadSessions ', @alterQuery); - PREPARE stmt FROM @query; - EXECUTE stmt; - DEALLOCATE PREPARE stmt; - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateUploadSessions procedure starting.') AS DEBUG; -CALL MigrateUploadSessions(); -SELECT CONCAT('-- ', NOW(), ' MigrateUploadSessions procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateUploadSessions; - -/* ==> mysql/000055_create_crt_thread_count_and_unreads.up.sql <== */ -/* fixCRTThreadCountsAndUnreads Marks threads as read for users where the last -reply time of the thread is earlier than the time the user viewed the channel. -Marking a thread means setting the mention count to zero and setting the -last viewed at time of the the thread as the last viewed at time -of the channel */ -DELIMITER // -CREATE PROCEDURE MigrateThreadMemberships () -BEGIN - -- UPDATE ThreadMemberships SET LastViewed = ..., UnreadMentions = ..., LastUpdated = ... - DECLARE UpdateThreadMemberships BOOLEAN; - DECLARE UpdateThreadMembershipsQuery TEXT DEFAULT NULL; - - SELECT COUNT(*) = 0 FROM Systems - WHERE Name = 'CRTThreadCountsAndUnreadsMigrationComplete' - INTO UpdateThreadMemberships; - - IF UpdateThreadMemberships THEN - UPDATE ThreadMemberships INNER JOIN ( - SELECT PostId, UserId, ChannelMembers.LastViewedAt AS CM_LastViewedAt, Threads.LastReplyAt - FROM Threads INNER JOIN ChannelMembers ON ChannelMembers.ChannelId = Threads.ChannelId - WHERE Threads.LastReplyAt <= ChannelMembers.LastViewedAt - ) AS q ON ThreadMemberships.Postid = q.PostId AND ThreadMemberships.UserId = q.UserId - SET LastViewed = q.CM_LastViewedAt + 1, UnreadMentions = 0, LastUpdated = (SELECT (SELECT ROUND(UNIX_TIMESTAMP(NOW(3))*1000))); - INSERT INTO Systems VALUES('CRTThreadCountsAndUnreadsMigrationComplete', 'true'); - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateThreadMemberships procedure starting.') AS DEBUG; -CALL MigrateThreadMemberships(); -SELECT CONCAT('-- ', NOW(), ' MigrateThreadMemberships procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateThreadMemberships; - -/* ==> mysql/000056_upgrade_channels_v6.0.up.sql <== */ -/* ==> mysql/000070_upgrade_cte_v6.1.up.sql <== */ -/* ==> mysql/000090_create_enums.up.sql <== */ -/* ==> mysql/000076_upgrade_lastrootpostat.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateChannels () -BEGIN - -- 'DROP INDEX idx_channels_team_id ON Channels;' - DECLARE DropIndex BOOLEAN; - DECLARE DropIndexQuery TEXT DEFAULT NULL; - - -- 'CREATE INDEX idx_channels_team_id_display_name ON Channels(TeamId, DisplayName);' - DECLARE CreateIndexTeamDisplay BOOLEAN; - DECLARE CreateIndexTeamDisplayQuery TEXT DEFAULT NULL; - - -- 'CREATE INDEX idx_channels_team_id_type ON Channels(TeamId, Type);' - DECLARE CreateIndexTeamType BOOLEAN; - DECLARE CreateIndexTeamTypeQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Channels ADD COLUMN LastRootPostAt bigint DEFAULT 0;'' - -- UPDATE Channels INNER JOIN ... - DECLARE AddLastRootPostAt BOOLEAN; - DECLARE AddLastRootPostAtQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Channels MODIFY COLUMN Type ENUM("D", "O", "G", "P");', - DECLARE ModifyColumn BOOLEAN; - DECLARE ModifyColumnQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Channels ALTER COLUMN LastRootPostAt SET DEFAULT 0;', - DECLARE SetDefault BOOLEAN; - DECLARE SetDefaultQuery TEXT DEFAULT NULL; - - -- 'UPDATE Channels SET LastRootPostAt = ...', - DECLARE UpdateLastRootPostAt BOOLEAN; - DECLARE UpdateLastRootPostAtQuery TEXT DEFAULT NULL; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Channels' - AND table_schema = DATABASE() - AND index_name = 'idx_channels_team_id' - INTO DropIndex; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Channels' - AND table_schema = DATABASE() - AND index_name = 'idx_channels_team_id_display_name' - INTO CreateIndexTeamDisplay; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Channels' - AND table_schema = DATABASE() - AND index_name = 'idx_channels_team_id_type' - INTO CreateIndexTeamType; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_NAME = 'Channels' - AND table_schema = DATABASE() - AND COLUMN_NAME = 'LastRootPostAt' - INTO AddLastRootPostAt; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Channels' - AND table_schema = DATABASE() - AND column_name = 'Type' - AND REPLACE(LOWER(column_type), '"', "'") != "enum('d','o','g','p')" - INTO ModifyColumn; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_NAME = 'Channels' - AND TABLE_SCHEMA = DATABASE() - AND COLUMN_NAME = 'LastRootPostAt' - AND (COLUMN_DEFAULT IS NULL OR COLUMN_DEFAULT != 0) - INTO SetDefault; - - IF DropIndex THEN - SET DropIndexQuery = 'DROP INDEX idx_channels_team_id'; - END IF; - - IF CreateIndexTeamDisplay THEN - SET CreateIndexTeamDisplayQuery = 'ADD INDEX idx_channels_team_id_display_name (TeamId, DisplayName)'; - END IF; - - IF CreateIndexTeamType THEN - SET CreateIndexTeamTypeQuery = 'ADD INDEX idx_channels_team_id_type (TeamId, Type)'; - END IF; - - IF AddLastRootPostAt THEN - SET AddLastRootPostAtQuery = 'ADD COLUMN LastRootPostAt bigint DEFAULT 0'; - END IF; - - IF ModifyColumn THEN - SET ModifyColumnQuery = 'MODIFY COLUMN Type ENUM("D", "O", "G", "P")'; - END IF; - - IF SetDefault THEN - SET SetDefaultQuery = 'ALTER COLUMN LastRootPostAt SET DEFAULT 0'; - END IF; - - SET @alterQuery = CONCAT_WS(', ', DropIndexQuery, CreateIndexTeamDisplayQuery, CreateIndexTeamTypeQuery, AddLastRootPostAtQuery, ModifyColumnQuery, SetDefaultQuery); - IF @alterQuery <> '' THEN - SET @query = CONCAT('ALTER TABLE Channels ', @alterQuery); - PREPARE stmt FROM @query; - EXECUTE stmt; - DEALLOCATE PREPARE stmt; - END IF; - - IF AddLastRootPostAt THEN - UPDATE Channels INNER JOIN ( - SELECT Channels.Id channelid, COALESCE(MAX(Posts.CreateAt), 0) AS lastrootpost - FROM Channels LEFT JOIN Posts FORCE INDEX (idx_posts_channel_id_update_at) ON Channels.Id = Posts.ChannelId - WHERE Posts.RootId = '' GROUP BY Channels.Id - ) AS q ON q.channelid = Channels.Id - SET LastRootPostAt = lastrootpost; - END IF; - - -- Cover the case where LastRootPostAt was already present and there are rows with it set to NULL - IF (SELECT COUNT(*) FROM Channels WHERE LastRootPostAt IS NULL) THEN - -- fixes migrate cte and sets the LastRootPostAt for channels that don't have it set - UPDATE Channels INNER JOIN ( - SELECT Channels.Id channelid, COALESCE(MAX(Posts.CreateAt), 0) AS lastrootpost - FROM Channels LEFT JOIN Posts FORCE INDEX (idx_posts_channel_id_update_at) ON Channels.Id = Posts.ChannelId - WHERE Posts.RootId = '' - GROUP BY Channels.Id - ) AS q ON q.channelid = Channels.Id - SET LastRootPostAt = lastrootpost - WHERE LastRootPostAt IS NULL; - -- sets LastRootPostAt to 0, for channels with no posts - UPDATE Channels SET LastRootPostAt=0 WHERE LastRootPostAt IS NULL; - END IF; - -END// -DELIMITER ; - -SELECT CONCAT('-- ', NOW(), ' MigrateChannels procedure starting.') AS DEBUG; -CALL MigrateChannels(); -SELECT CONCAT('-- ', NOW(), ' MigrateChannels procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateChannels; - -/* ==> mysql/000057_upgrade_command_webhooks_v6.0.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateCommandWebhooks () -BEGIN - DECLARE DropParentId BOOLEAN; - - SELECT COUNT(*) - FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_NAME = 'CommandWebhooks' - AND table_schema = DATABASE() - AND COLUMN_NAME = 'ParentId' - INTO DropParentId; - - IF DropParentId THEN - UPDATE CommandWebhooks SET RootId = ParentId WHERE RootId = '' AND RootId != ParentId; - ALTER TABLE CommandWebhooks DROP COLUMN ParentId; - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateCommandWebhooks procedure starting.') AS DEBUG; -CALL MigrateCommandWebhooks(); -SELECT CONCAT('-- ', NOW(), ' MigrateCommandWebhooks procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateCommandWebhooks; - -/* ==> mysql/000054_create_crt_channelmembership_count.up.sql <== */ -/* ==> mysql/000058_upgrade_channelmembers_v6.0.up.sql <== */ -/* ==> mysql/000067_upgrade_channelmembers_v6.1.up.sql <== */ -/* ==> mysql/000097_create_posts_priority.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateChannelMembers () -BEGIN - -- 'ALTER TABLE ChannelMembers MODIFY COLUMN NotifyProps JSON;', - DECLARE ModifyNotifyProps BOOLEAN; - DECLARE ModifyNotifyPropsQuery TEXT DEFAULT NULL; - - -- 'DROP INDEX idx_channelmembers_user_id ON ChannelMembers;', - DECLARE DropIndex BOOLEAN; - DECLARE DropIndexQuery TEXT DEFAULT NULL; - - -- 'CREATE INDEX idx_channelmembers_user_id_channel_id_last_viewed_at ON ChannelMembers(UserId, ChannelId, LastViewedAt);' - DECLARE CreateIndexLastViewedAt BOOLEAN; - DECLARE CreateIndexLastViewedAtQuery TEXT DEFAULT NULL; - - -- 'CREATE INDEX idx_channelmembers_channel_id_scheme_guest_user_id ON ChannelMembers(ChannelId, SchemeGuest, UserId);' - DECLARE CreateIndexSchemeGuest BOOLEAN; - DECLARE CreateIndexSchemeGuestQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE ChannelMembers MODIFY COLUMN Roles text;', - DECLARE ModifyRoles BOOLEAN; - DECLARE ModifyRolesQuery TEXT DEFAULT NOT NULL; - - -- 'ALTER TABLE ChannelMembers ADD COLUMN UrgentMentionCount bigint(20);', - DECLARE AddUrgentMentionCount BOOLEAN; - DECLARE AddUrgentMentionCountQuery TEXT DEFAULT NOT NULL; - - DECLARE MigrateMemberships BOOLEAN; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'ChannelMembers' - AND table_schema = DATABASE() - AND column_name = 'NotifyProps' - AND LOWER(column_type) != 'json' - INTO ModifyNotifyProps; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'ChannelMembers' - AND table_schema = DATABASE() - AND index_name = 'idx_channelmembers_user_id' - INTO DropIndex; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'ChannelMembers' - AND table_schema = DATABASE() - AND index_name = 'idx_channelmembers_user_id_channel_id_last_viewed_at' - INTO CreateIndexLastViewedAt; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'ChannelMembers' - AND table_schema = DATABASE() - AND index_name = 'idx_channelmembers_channel_id_scheme_guest_user_id' - INTO CreateIndexSchemeGuest; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'ChannelMembers' - AND table_schema = DATABASE() - AND column_name = 'Roles' - AND LOWER(column_type) != 'text' - INTO ModifyRoles; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'ChannelMembers' - AND table_schema = DATABASE() - AND column_name = 'UrgentMentionCount' - INTO AddUrgentMentionCount; - - SELECT COUNT(*) = 0 FROM Systems - WHERE Name = 'CRTChannelMembershipCountsMigrationComplete' - INTO MigrateMemberships; - - IF ModifyNotifyProps THEN - SET ModifyNotifyPropsQuery = 'MODIFY COLUMN NotifyProps JSON'; - END IF; - - IF DropIndex THEN - SET DropIndexQuery = 'DROP INDEX idx_channelmembers_user_id'; - END IF; - - IF CreateIndexLastViewedAt THEN - SET CreateIndexLastViewedAtQuery = 'ADD INDEX idx_channelmembers_user_id_channel_id_last_viewed_at (UserId, ChannelId, LastViewedAt)'; - END IF; - - IF CreateIndexSchemeGuest THEN - SET CreateIndexSchemeGuestQuery = 'ADD INDEX idx_channelmembers_channel_id_scheme_guest_user_id (ChannelId, SchemeGuest, UserId)'; - END IF; - - IF ModifyRoles THEN - SET ModifyRolesQuery = 'MODIFY COLUMN Roles text'; - END IF; - - IF AddUrgentMentionCount THEN - SET AddUrgentMentionCountQuery = 'ADD COLUMN UrgentMentionCount bigint(20)'; - END IF; - - SET @alterQuery = CONCAT_WS(', ', ModifyNotifyPropsQuery, DropIndexQuery, CreateIndexLastViewedAtQuery, CreateIndexSchemeGuestQuery, ModifyRolesQuery, AddUrgentMentionCountQuery); - IF @alterQuery <> '' THEN - SET @query = CONCAT('ALTER TABLE ChannelMembers ', @alterQuery); - PREPARE stmt FROM @query; - EXECUTE stmt; - DEALLOCATE PREPARE stmt; - END IF; - - IF MigrateMemberships THEN - UPDATE ChannelMembers INNER JOIN Channels ON Channels.Id = ChannelMembers.ChannelId - SET MentionCount = 0, MentionCountRoot = 0, MsgCount = Channels.TotalMsgCount, MsgCountRoot = Channels.TotalMsgCountRoot, LastUpdateAt = (SELECT (SELECT ROUND(UNIX_TIMESTAMP(NOW(3))*1000))) - WHERE ChannelMembers.LastViewedAt >= Channels.LastPostAt; - INSERT INTO Systems VALUES('CRTChannelMembershipCountsMigrationComplete', 'true'); - END IF; - -END// -DELIMITER ; - -SELECT CONCAT('-- ', NOW(), ' MigrateChannelMembers procedure starting.') AS DEBUG; -CALL MigrateChannelMembers(); -SELECT CONCAT('-- ', NOW(), ' MigrateChannelMembers procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateChannelMembers; - -/* ==> mysql/000059_upgrade_users_v6.0.up.sql <== */ -/* ==> mysql/000074_upgrade_users_v6.3.up.sql <== */ -/* ==> mysql/000077_upgrade_users_v6.5.up.sql <== */ -/* ==> mysql/000088_remaining_migrations.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateUsers () -BEGIN - -- 'ALTER TABLE Users MODIFY COLUMN Props JSON;', - DECLARE ChangeProps BOOLEAN; - DECLARE ChangePropsQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Users MODIFY COLUMN NotifyProps JSON;', - DECLARE ChangeNotifyProps BOOLEAN; - DECLARE ChangeNotifyPropsQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Users ALTER Timezone DROP DEFAULT;', - DECLARE DropTimezoneDefault BOOLEAN; - DECLARE DropTimezoneDefaultQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Users MODIFY COLUMN Timezone JSON;', - DECLARE ChangeTimezone BOOLEAN; - DECLARE ChangeTimezoneQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Users MODIFY COLUMN Roles text;', - DECLARE ChangeRoles BOOLEAN; - DECLARE ChangeRolesQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Users DROP COLUMN AcceptedTermsOfServiceId;', - DECLARE DropTermsOfService BOOLEAN; - DECLARE DropTermsOfServiceQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Users DROP COLUMN AcceptedServiceTermsId;', - DECLARE DropServiceTerms BOOLEAN; - DECLARE DropServiceTermsQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Users DROP COLUMN ThemeProps', - DECLARE DropThemeProps BOOLEAN; - DECLARE DropThemePropsQuery TEXT DEFAULT NULL; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'Props' - AND LOWER(column_type) != 'json' - INTO ChangeProps; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'NotifyProps' - AND LOWER(column_type) != 'json' - INTO ChangeNotifyProps; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND column_default IS NOT NULL - INTO DropTimezoneDefault; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'Timezone' - AND LOWER(column_type) != 'json' - INTO ChangeTimezone; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'Roles' - AND LOWER(column_type) != 'text' - INTO ChangeRoles; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'AcceptedTermsOfServiceId' - INTO DropTermsOfService; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'AcceptedServiceTermsId' - INTO DropServiceTerms; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'ThemeProps' - INTO DropThemeProps; - - IF ChangeProps THEN - SET ChangePropsQuery = 'MODIFY COLUMN Props JSON'; - END IF; - - IF ChangeNotifyProps THEN - SET ChangeNotifyPropsQuery = 'MODIFY COLUMN NotifyProps JSON'; - END IF; - - IF DropTimezoneDefault THEN - SET DropTimezoneDefaultQuery = 'ALTER Timezone DROP DEFAULT'; - END IF; - - IF ChangeTimezone THEN - SET ChangeTimezoneQuery = 'MODIFY COLUMN Timezone JSON'; - END IF; - - IF ChangeRoles THEN - SET ChangeRolesQuery = 'MODIFY COLUMN Roles text'; - END IF; - - IF DropTermsOfService THEN - SET DropTermsOfServiceQuery = 'DROP COLUMN AcceptedTermsOfServiceId'; - END IF; - - IF DropServiceTerms THEN - SET DropServiceTermsQuery = 'DROP COLUMN AcceptedServiceTermsId'; - END IF; - - IF DropThemeProps THEN - INSERT INTO Preferences(UserId, Category, Name, Value) SELECT Id, '', '', ThemeProps FROM Users WHERE Users.ThemeProps != 'null'; - SET DropThemePropsQuery = 'DROP COLUMN ThemeProps'; - END IF; - - SET @alterQuery = CONCAT_WS(', ', ChangePropsQuery, ChangeNotifyPropsQuery, DropTimezoneDefaultQuery, ChangeTimezoneQuery, ChangeRolesQuery, DropTermsOfServiceQuery, DropServiceTermsQuery, DropThemePropsQuery); - IF @alterQuery <> '' THEN - SET @query = CONCAT('ALTER TABLE Users ', @alterQuery); - PREPARE stmt FROM @query; - EXECUTE stmt; - DEALLOCATE PREPARE stmt; - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateUsers procedure starting.') AS DEBUG; -CALL MigrateUsers(); -SELECT CONCAT('-- ', NOW(), ' MigrateUsers procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateUsers; - -/* ==> mysql/000060_upgrade_jobs_v6.0.up.sql <== */ -/* ==> mysql/000069_upgrade_jobs_v6.1.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateJobs () -BEGIN - -- 'ALTER TABLE Jobs MODIFY COLUMN Data JSON;', - DECLARE ModifyData BOOLEAN; - DECLARE ModifyDataQuery TEXT DEFAULT NULL; - - -- 'CREATE INDEX idx_jobs_status_type ON Jobs(Status, Type);' - DECLARE CreateIndex BOOLEAN; - DECLARE CreateIndexQuery TEXT DEFAULT NULL; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Jobs' - AND table_schema = DATABASE() - AND column_name = 'Data' - AND LOWER(column_type) != 'JSON' - INTO ModifyData; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Jobs' - AND table_schema = DATABASE() - AND index_name = 'idx_jobs_status_type' - INTO CreateIndex; - - IF ModifyData THEN - SET ModifyDataQuery = 'MODIFY COLUMN Data JSON'; - END IF; - - IF CreateIndex THEN - SET CreateIndexQuery = 'ADD INDEX idx_jobs_status_type (Status, Type)'; - END IF; - - SET @alterQuery = CONCAT_WS(', ', ModifyDataQuery, CreateIndexQuery); - IF @alterQuery <> '' THEN - SET @query = CONCAT('ALTER TABLE Jobs ', @alterQuery); - PREPARE stmt FROM @query; - EXECUTE stmt; - DEALLOCATE PREPARE stmt; - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateJobs procedure starting.') AS DEBUG; -CALL MigrateJobs(); -SELECT CONCAT('-- ', NOW(), ' MigrateJobs procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateJobs; - -/* ==> mysql/000061_upgrade_link_metadata_v6.0.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateLinkMetadata () -BEGIN - -- ALTER TABLE LinkMetadata MODIFY COLUMN Data JSON; - DECLARE ModifyData BOOLEAN; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'LinkMetadata' - AND table_schema = DATABASE() - AND column_name = 'Data' - AND LOWER(column_type) != 'JSON' - INTO ModifyData; - - IF ModifyData THEN - ALTER TABLE LinkMetadata MODIFY COLUMN Data JSON; - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateLinkMetadata procedure starting.') AS DEBUG; -CALL MigrateLinkMetadata(); -SELECT CONCAT('-- ', NOW(), ' MigrateLinkMetadata procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateLinkMetadata; - -/* ==> mysql/000062_upgrade_sessions_v6.0.up.sql <== */ -/* ==> mysql/000071_upgrade_sessions_v6.1.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateSessions () -BEGIN - -- 'ALTER TABLE Sessions MODIFY COLUMN Props JSON;', - DECLARE ModifyProps BOOLEAN; - DECLARE ModifyPropsQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Sessions MODIFY COLUMN Roles text;', - DECLARE ModifyRoles BOOLEAN; - DECLARE ModifyRolesQuery TEXT DEFAULT NULL; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Sessions' - AND table_schema = DATABASE() - AND column_name = 'Props' - AND LOWER(column_type) != 'json' - INTO ModifyProps; - - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Sessions' - AND table_schema = DATABASE() - AND column_name = 'Roles' - AND LOWER(column_type) != 'text' - INTO ModifyRoles; - - IF ModifyProps THEN - SET ModifyPropsQuery = 'MODIFY COLUMN Props JSON'; - END IF; - - IF ModifyRoles THEN - SET ModifyRolesQuery = 'MODIFY COLUMN Roles text'; - END IF; - - SET @alterQuery = CONCAT_WS(', ', ModifyPropsQuery, ModifyRolesQuery); - IF @alterQuery <> '' THEN - SET @query = CONCAT('ALTER TABLE Sessions ', @alterQuery); - PREPARE stmt FROM @query; - EXECUTE stmt; - DEALLOCATE PREPARE stmt; - END IF; - -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateSessions procedure starting.') AS DEBUG; -CALL MigrateSessions(); -SELECT CONCAT('-- ', NOW(), ' MigrateSessions procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateSessions; - -/* ==> mysql/000063_upgrade_threads_v6.0.up.sql <== */ -/* ==> mysql/000083_threads_threaddeleteat.up.sql <== */ -/* ==> mysql/000096_threads_threadteamid.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateThreads () -BEGIN - -- 'ALTER TABLE Threads MODIFY COLUMN Participants JSON;' - DECLARE ChangeParticipants BOOLEAN; - DECLARE ChangeParticipantsQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Threads DROP COLUMN DeleteAt;' - DECLARE DropDeleteAt BOOLEAN; - DECLARE DropDeleteAtQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Threads ADD COLUMN ThreadDeleteAt bigint(20);' - DECLARE CreateThreadDeleteAt BOOLEAN; - DECLARE CreateThreadDeleteAtQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Threads DROP COLUMN TeamId;' - DECLARE DropTeamId BOOLEAN; - DECLARE DropTeamIdQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Threads ADD COLUMN ThreadTeamId varchar(26) DEFAULT NULL;' - DECLARE CreateThreadTeamId BOOLEAN; - DECLARE CreateThreadTeamIdQuery TEXT DEFAULT NULL; - - -- CREATE INDEX idx_threads_channel_id_last_reply_at ON Threads(ChannelId, LastReplyAt); - DECLARE CreateIndex BOOLEAN; - DECLARE CreateIndexQuery TEXT DEFAULT NULL; - - -- DROP INDEX idx_threads_channel_id ON Threads; - DECLARE DropIndex BOOLEAN; - DECLARE DropIndexQuery TEXT DEFAULT NULL; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Threads' - AND table_schema = DATABASE() - AND column_name = 'Participants' - AND LOWER(column_type) != 'json' - INTO ChangeParticipants; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Threads' - AND table_schema = DATABASE() - AND column_name = 'DeleteAt' - INTO DropDeleteAt; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Threads' - AND table_schema = DATABASE() - AND column_name = 'ThreadDeleteAt' - INTO CreateThreadDeleteAt; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Threads' - AND table_schema = DATABASE() - AND column_name = 'TeamId' - INTO DropTeamId; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Threads' - AND table_schema = DATABASE() - AND column_name = 'ThreadTeamId' - INTO CreateThreadTeamId; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Threads' - AND table_schema = DATABASE() - AND index_name = 'idx_threads_channel_id_last_reply_at' - INTO CreateIndex; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Threads' - AND table_schema = DATABASE() - AND index_name = 'idx_threads_channel_id' - INTO DropIndex; - - IF ChangeParticipants THEN - SET ChangeParticipantsQuery = 'MODIFY COLUMN Participants JSON'; - END IF; - - IF DropDeleteAt THEN - SET DropDeleteAtQuery = 'DROP COLUMN DeleteAt'; - END IF; - - IF CreateThreadDeleteAt THEN - SET CreateThreadDeleteAtQuery = 'ADD COLUMN ThreadDeleteAt bigint(20)'; - END IF; - - IF DropTeamId THEN - SET DropTeamIdQuery = 'DROP COLUMN TeamId'; - END IF; - - IF CreateThreadTeamId THEN - SET CreateThreadTeamIdQuery = 'ADD COLUMN ThreadTeamId varchar(26) DEFAULT NULL'; - END IF; - - IF CreateIndex THEN - SET CreateIndexQuery = 'ADD INDEX idx_threads_channel_id_last_reply_at (ChannelId, LastReplyAt)'; - END IF; - - IF DropIndex THEN - SET DropIndexQuery = 'DROP INDEX idx_threads_channel_id'; - END IF; - - SET @alterQuery = CONCAT_WS(', ', ChangeParticipantsQuery, DropDeleteAtQuery, CreateThreadDeleteAtQuery, DropTeamIdQuery, CreateThreadTeamIdQuery, CreateIndexQuery, DropIndexQuery); - IF @alterQuery <> '' THEN - SET @query = CONCAT('ALTER TABLE Threads ', @alterQuery); - PREPARE stmt FROM @query; - EXECUTE stmt; - DEALLOCATE PREPARE stmt; - END IF; - - UPDATE Threads, Posts - SET Threads.ThreadDeleteAt = Posts.DeleteAt - WHERE Posts.Id = Threads.PostId - AND Threads.ThreadDeleteAt IS NULL; - - UPDATE Threads, Channels - SET Threads.ThreadTeamId = Channels.TeamId - WHERE Channels.Id = Threads.ChannelId - AND Threads.ThreadTeamId IS NULL; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateThreads procedure starting.') AS DEBUG; -CALL MigrateThreads(); -SELECT CONCAT('-- ', NOW(), ' MigrateThreads procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateThreads; - -/* ==> mysql/000064_upgrade_status_v6.0.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateStatus () -BEGIN - -- 'CREATE INDEX idx_status_status_dndendtime ON Status(Status, DNDEndTime);' - DECLARE CreateIndex BOOLEAN; - DECLARE CreateIndexQuery TEXT DEFAULT NULL; - - -- 'DROP INDEX idx_status_status ON Status;', - DECLARE DropIndex BOOLEAN; - DECLARE DropIndexQuery TEXT DEFAULT NULL; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Status' - AND table_schema = DATABASE() - AND index_name = 'idx_status_status_dndendtime' - INTO CreateIndex; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Status' - AND table_schema = DATABASE() - AND index_name = 'idx_status_status' - INTO DropIndex; - - IF CreateIndex THEN - SET CreateIndexQuery = 'ADD INDEX idx_status_status_dndendtime (Status, DNDEndTime)'; - END IF; - - IF DropIndex THEN - SET DropIndexQuery = 'DROP INDEX idx_status_status'; - END IF; - - SET @alterQuery = CONCAT_WS(', ', CreateIndexQuery, DropIndexQuery); - IF @alterQuery <> '' THEN - SET @query = CONCAT('ALTER TABLE Status ', @alterQuery); - PREPARE stmt FROM @query; - EXECUTE stmt; - DEALLOCATE PREPARE stmt; - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateStatus procedure starting.') AS DEBUG; -CALL MigrateStatus (); -SELECT CONCAT('-- ', NOW(), ' MigrateStatus procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateStatus; - -/* ==> mysql/000065_upgrade_groupchannels_v6.0.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateGroupChannels () -BEGIN - -- 'CREATE INDEX idx_groupchannels_schemeadmin ON GroupChannels(SchemeAdmin);' - DECLARE CreateIndex BOOLEAN; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'GroupChannels' - AND table_schema = DATABASE() - AND index_name = 'idx_groupchannels_schemeadmin' - INTO CreateIndex; - - IF CreateIndex THEN - CREATE INDEX idx_groupchannels_schemeadmin ON GroupChannels(SchemeAdmin); - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateGroupChannels procedure starting.') AS DEBUG; -CALL MigrateGroupChannels (); -SELECT CONCAT('-- ', NOW(), ' MigrateGroupChannels procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateGroupChannels; - -/* ==> mysql/000066_upgrade_posts_v6.0.up.sql <== */ -/* ==> mysql/000080_posts_createat_id.up.sql <== */ -/* ==> mysql/000095_remove_posts_parentid.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigratePosts () -BEGIN - -- DROP COLUMN ParentId - DECLARE DropParentId BOOLEAN; - DECLARE DropParentIdQuery TEXT DEFAULT NULL; - - -- MODIFY COLUMN FileIds - DECLARE ModifyFileIds BOOLEAN; - DECLARE ModifyFileIdsQuery TEXT DEFAULT NULL; - - -- MODIFY COLUMN Props - DECLARE ModifyProps BOOLEAN; - DECLARE ModifyPropsQuery TEXT DEFAULT NULL; - - -- 'CREATE INDEX idx_posts_root_id_delete_at ON Posts(RootId, DeleteAt);' - DECLARE CreateIndexRootId BOOLEAN; - DECLARE CreateIndexRootIdQuery TEXT DEFAULT NULL; - - -- 'DROP INDEX idx_posts_root_id ON Posts;', - DECLARE DropIndex BOOLEAN; - DECLARE DropIndexQuery TEXT DEFAULT NULL; - - -- 'CREATE INDEX idx_posts_create_at_id on Posts(CreateAt, Id) LOCK=NONE;' - DECLARE CreateIndexCreateAt BOOLEAN; - DECLARE CreateIndexCreateAtQuery TEXT DEFAULT NULL; - - -- Condition to control whether to update the RootId column. - DECLARE UpdateRootId BOOLEAN; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_NAME = 'Posts' - AND table_schema = DATABASE() - AND COLUMN_NAME = 'ParentId' - INTO DropParentId; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Posts' - AND table_schema = DATABASE() - AND column_name = 'FileIds' - AND LOWER(column_type) != 'text' - INTO ModifyFileIds; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Posts' - AND table_schema = DATABASE() - AND column_name = 'Props' - AND LOWER(column_type) != 'json' - INTO ModifyProps; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Posts' - AND table_schema = DATABASE() - AND index_name = 'idx_posts_root_id_delete_at' - INTO CreateIndexRootId; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Posts' - AND table_schema = DATABASE() - AND index_name = 'idx_posts_root_id' - INTO DropIndex; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Posts' - AND table_schema = DATABASE() - AND index_name = 'idx_posts_create_at_id' - INTO CreateIndexCreateAt; - - IF DropParentId THEN - SET DropParentIdQuery = 'DROP COLUMN ParentId'; - SELECT COUNT(*) FROM Posts WHERE RootId != ParentId INTO UpdateRootId; - IF UpdateRootId THEN - UPDATE Posts SET RootId = ParentId WHERE RootId = '' AND RootId != ParentId; - END IF; - END IF; - - IF ModifyFileIds THEN - SET ModifyFileIdsQuery = 'MODIFY COLUMN FileIds text'; - END IF; - - IF ModifyProps THEN - SET ModifyPropsQuery = 'MODIFY COLUMN Props JSON'; - END IF; - - IF CreateIndexRootId THEN - SET CreateIndexRootIdQuery = 'ADD INDEX idx_posts_root_id_delete_at (RootId, DeleteAt)'; - END IF; - - IF DropIndex THEN - SET DropIndexQuery = 'DROP INDEX idx_posts_root_id'; - END IF; - - IF CreateIndexCreateAt THEN - SET CreateIndexCreateAtQuery = 'ADD INDEX idx_posts_create_at_id (CreateAt, Id)'; - END IF; - - SET @alterQuery = CONCAT_WS(', ', DropParentIdQuery, ModifyFileIdsQuery, ModifyPropsQuery, CreateIndexRootIdQuery, DropIndexQuery, CreateIndexCreateAtQuery); - IF @alterQuery <> '' THEN - SET @query = CONCAT('ALTER TABLE Posts ', @alterQuery); - PREPARE stmt FROM @query; - EXECUTE stmt; - DEALLOCATE PREPARE stmt; - END IF; - -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigratePosts procedure starting.') AS DEBUG; -CALL MigratePosts (); -SELECT CONCAT('-- ', NOW(), ' MigratePosts procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigratePosts; - -/* ==> mysql/000068_upgrade_teammembers_v6.1.up.sql <== */ -/* ==> mysql/000092_add_createat_to_teammembers.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateTeamMembers () -BEGIN - -- 'ALTER TABLE TeamMembers MODIFY COLUMN Roles text;', - DECLARE ModifyRoles BOOLEAN; - DECLARE ModifyRolesQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE TeamMembers ADD COLUMN CreateAt bigint DEFAULT 0;', - DECLARE AddCreateAt BOOLEAN; - DECLARE AddCreateAtQuery TEXT DEFAULT NULL; - - -- 'CREATE INDEX idx_teammembers_createat ON TeamMembers(CreateAt);' - DECLARE CreateIndex BOOLEAN; - DECLARE CreateIndexQuery TEXT DEFAULT NULL; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'TeamMembers' - AND table_schema = DATABASE() - AND column_name = 'Roles' - AND LOWER(column_type) != 'text' - INTO ModifyRoles; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'TeamMembers' - AND table_schema = DATABASE() - AND column_name = 'CreateAt' - INTO AddCreateAt; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'TeamMembers' - AND table_schema = DATABASE() - AND index_name = 'idx_teammembers_createat' - INTO CreateIndex; - - IF ModifyRoles THEN - SET ModifyRolesQuery = 'MODIFY COLUMN Roles text'; - END IF; - - IF AddCreateAt THEN - SET AddCreateAtQuery = 'ADD COLUMN CreateAt bigint DEFAULT 0'; - END IF; - - IF CreateIndex THEN - SET CreateIndexQuery = 'ADD INDEX idx_teammembers_createat (CreateAt)'; - END IF; - - SET @alterQuery = CONCAT_WS(', ', ModifyRolesQuery, AddCreateAtQuery, CreateIndexQuery); - IF @alterQuery <> '' THEN - SET @query = CONCAT('ALTER TABLE TeamMembers ', @alterQuery); - PREPARE stmt FROM @query; - EXECUTE stmt; - DEALLOCATE PREPARE stmt; - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateTeamMembers procedure starting.') AS DEBUG; -CALL MigrateTeamMembers (); -SELECT CONCAT('-- ', NOW(), ' MigrateTeamMembers procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateTeamMembers; - -/* ==> mysql/000072_upgrade_schemes_v6.3.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateSchemes () -BEGIN - -- 'ALTER TABLE Schemes ADD COLUMN DefaultPlaybookAdminRole VARCHAR(64) DEFAULT "";' - DECLARE AddDefaultPlaybookAdminRole BOOLEAN; - DECLARE AddDefaultPlaybookAdminRoleQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Schemes ADD COLUMN DefaultPlaybookMemberRole VARCHAR(64) DEFAULT "";' - DECLARE AddDefaultPlaybookMemberRole BOOLEAN; - DECLARE AddDefaultPlaybookMemberRoleQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Schemes ADD COLUMN DefaultRunAdminRole VARCHAR(64) DEFAULT "";' - DECLARE AddDefaultRunAdminRole BOOLEAN; - DECLARE AddDefaultRunAdminRoleQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Schemes ADD COLUMN DefaultRunMemberRole VARCHAR(64) DEFAULT "";' - DECLARE AddDefaultRunMemberRole BOOLEAN; - DECLARE AddDefaultRunMemberRoleQuery TEXT DEFAULT NULL; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Schemes' - AND table_schema = DATABASE() - AND column_name = 'DefaultPlaybookAdminRole' - INTO AddDefaultPlaybookAdminRole; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Schemes' - AND table_schema = DATABASE() - AND column_name = 'DefaultPlaybookMemberRole' - INTO AddDefaultPlaybookMemberRole; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Schemes' - AND table_schema = DATABASE() - AND column_name = 'DefaultRunAdminRole' - INTO AddDefaultRunAdminRole; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Schemes' - AND table_schema = DATABASE() - AND column_name = 'DefaultRunMemberRole' - INTO AddDefaultRunMemberRole; - - IF AddDefaultPlaybookAdminRole THEN - SET AddDefaultPlaybookAdminRoleQuery = 'ADD COLUMN DefaultPlaybookAdminRole VARCHAR(64) DEFAULT ""'; - END IF; - - IF AddDefaultPlaybookMemberRole THEN - SET AddDefaultPlaybookMemberRoleQuery = 'ADD COLUMN DefaultPlaybookMemberRole VARCHAR(64) DEFAULT ""'; - END IF; - - IF AddDefaultRunAdminRole THEN - SET AddDefaultRunAdminRoleQuery = 'ADD COLUMN DefaultRunAdminRole VARCHAR(64) DEFAULT ""'; - END IF; - - IF AddDefaultRunMemberRole THEN - SET AddDefaultRunMemberRoleQuery = 'ADD COLUMN DefaultRunMemberRole VARCHAR(64) DEFAULT ""'; - END IF; - - SET @alterQuery = CONCAT_WS(', ', AddDefaultPlaybookAdminRoleQuery, AddDefaultPlaybookMemberRoleQuery, AddDefaultRunAdminRoleQuery, AddDefaultRunMemberRoleQuery); - IF @alterQuery <> '' THEN - SET @query = CONCAT('ALTER TABLE Schemes ', @alterQuery); - PREPARE stmt FROM @query; - EXECUTE stmt; - DEALLOCATE PREPARE stmt; - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateSchemes procedure starting.') AS DEBUG; -CALL MigrateSchemes (); -SELECT CONCAT('-- ', NOW(), ' MigrateSchemes procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateSchemes; - -/* ==> mysql/000073_upgrade_plugin_key_value_store_v6.3.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigratePluginKeyValueStore () -BEGIN - -- 'ALTER TABLE PluginKeyValueStore MODIFY COLUMN PKey varchar(150);', - DECLARE ModifyPKey BOOLEAN; - - SELECT COUNT(*) FROM Information_Schema.Columns - WHERE table_name = 'PluginKeyValueStore' - AND table_schema = DATABASE() - AND column_name = 'PKey' - AND LOWER(column_type) != 'varchar(150)' - INTO ModifyPKey; - - IF ModifyPKey THEN - ALTER TABLE PluginKeyValueStore MODIFY COLUMN PKey varchar(150); - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigratePluginKeyValueStore procedure starting.') AS DEBUG; -CALL MigratePluginKeyValueStore (); -SELECT CONCAT('-- ', NOW(), ' MigratePluginKeyValueStore procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigratePluginKeyValueStore; - -/* ==> mysql/000078_create_oauth_mattermost_app_id.up.sql <== */ -/* ==> mysql/000082_upgrade_oauth_mattermost_app_id.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateOAuthApps () -BEGIN - -- 'ALTER TABLE OAuthApps ADD COLUMN MattermostAppID varchar(32);' - DECLARE AddMattermostAppID BOOLEAN; - DECLARE AddMattermostAppIDQuery TEXT DEFAULT NULL; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'OAuthApps' - AND table_schema = DATABASE() - AND column_name = 'MattermostAppID' - INTO AddMattermostAppID; - - IF AddMattermostAppID THEN - SET AddMattermostAppIDQuery = 'ADD COLUMN MattermostAppID varchar(32) NOT NULL DEFAULT ""'; - SET @query = CONCAT('ALTER TABLE OAuthApps ', CONCAT_WS(', ', AddMattermostAppIDQuery)); - PREPARE stmt FROM @query; - EXECUTE stmt; - DEALLOCATE PREPARE stmt; - END IF; - - IF AddMattermostAppID THEN - UPDATE OAuthApps SET MattermostAppID = "" WHERE MattermostAppID IS NULL; - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateOAuthApps procedure starting.') AS DEBUG; -CALL MigrateOAuthApps (); -SELECT CONCAT('-- ', NOW(), ' MigrateOAuthApps procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateOAuthApps; - -/* ==> mysql/000079_usergroups_displayname_index.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateUserGroups () -BEGIN - -- 'CREATE INDEX idx_usergroups_displayname ON UserGroups(DisplayName);' - DECLARE CreateIndex BOOLEAN; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'UserGroups' - AND table_schema = DATABASE() - AND index_name = 'idx_usergroups_displayname' - INTO CreateIndex; - - IF CreateIndex THEN - CREATE INDEX idx_usergroups_displayname ON UserGroups(DisplayName); - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateUserGroups procedure starting.') AS DEBUG; -CALL MigrateUserGroups (); -SELECT CONCAT('-- ', NOW(), ' MigrateUserGroups procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateUserGroups; - -/* ==> mysql/000081_threads_deleteat.up.sql <== */ --- Replaced by 000083_threads_threaddeleteat.up.sql - -/* ==> mysql/000084_recent_searches.up.sql <== */ -CREATE TABLE IF NOT EXISTS RecentSearches ( - UserId CHAR(26), - SearchPointer int, - Query json, - CreateAt bigint NOT NULL, - PRIMARY KEY (UserId, SearchPointer) -); - -/* ==> mysql/000085_fileinfo_add_archived_column.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateFileInfo () -BEGIN - -- 'ALTER TABLE FileInfo ADD COLUMN Archived boolean NOT NULL DEFAULT false;' - DECLARE AddArchived BOOLEAN; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'FileInfo' - AND table_schema = DATABASE() - AND column_name = 'Archived' - INTO AddArchived; - - IF AddArchived THEN - ALTER TABLE FileInfo ADD COLUMN Archived boolean NOT NULL DEFAULT false; - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateFileInfo procedure starting.') AS DEBUG; -CALL MigrateFileInfo (); -SELECT CONCAT('-- ', NOW(), ' MigrateFileInfo procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateFileInfo; - -/* ==> mysql/000086_add_cloud_limits_archived.up.sql <== */ -/* ==> mysql/000090_create_enums.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateTeams () -BEGIN - -- 'ALTER TABLE Teams ADD COLUMN CloudLimitsArchived BOOLEAN NOT NULL DEFAULT FALSE;', - DECLARE AddCloudLimitsArchived BOOLEAN; - DECLARE AddCloudLimitsArchivedQuery TEXT DEFAULT NULL; - - -- 'ALTER TABLE Teams MODIFY COLUMN Type ENUM("I", "O");', - DECLARE ModifyType BOOLEAN; - DECLARE ModifyTypeQuery TEXT DEFAULT NULL; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Teams' - AND table_schema = DATABASE() - AND column_name = 'CloudLimitsArchived' - INTO AddCloudLimitsArchived; - - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Teams' - AND table_schema = DATABASE() - AND column_name = 'Type' - AND REPLACE(LOWER(column_type), '"', "'") != "enum('i','o')" - INTO ModifyType; - - IF AddCloudLimitsArchived THEN - SET AddCloudLimitsArchivedQuery = 'ADD COLUMN CloudLimitsArchived BOOLEAN NOT NULL DEFAULT FALSE'; - END IF; - - IF ModifyType THEN - SET ModifyTypeQuery = 'MODIFY COLUMN Type ENUM("I", "O")'; - END IF; - - SET @alterQuery = CONCAT_WS(', ', AddCloudLimitsArchivedQuery, ModifyTypeQuery); - IF @alterQuery <> '' THEN - SET @query = CONCAT('ALTER TABLE Teams ', @alterQuery); - PREPARE stmt FROM @query; - EXECUTE stmt; - DEALLOCATE PREPARE stmt; - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateTeams procedure starting.') AS DEBUG; -CALL MigrateTeams (); -SELECT CONCAT('-- ', NOW(), ' MigrateTeams procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateTeams; - -/* ==> mysql/000087_sidebar_categories_index.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateSidebarCategories () -BEGIN - -- 'CREATE INDEX idx_sidebarcategories_userid_teamid on SidebarCategories(UserId, TeamId) LOCK=NONE;' - DECLARE CreateIndex BOOLEAN; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'SidebarCategories' - AND table_schema = DATABASE() - AND index_name = 'idx_sidebarcategories_userid_teamid' - INTO CreateIndex; - - IF CreateIndex THEN - CREATE INDEX idx_sidebarcategories_userid_teamid on SidebarCategories(UserId, TeamId) LOCK=NONE; - END IF; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateSidebarCategories procedure starting.') AS DEBUG; -CALL MigrateSidebarCategories (); -SELECT CONCAT('-- ', NOW(), ' MigrateSidebarCategories procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateSidebarCategories; - -/* ==> mysql/000088_remaining_migrations.up.sql <== */ -DROP TABLE IF EXISTS JobStatuses; -DROP TABLE IF EXISTS PasswordRecovery; - -/* ==> mysql/000089_add-channelid-to-reaction.up.sql <== */ -DELIMITER // -CREATE PROCEDURE MigrateReactions () -BEGIN - -- 'ALTER TABLE Reactions ADD COLUMN ChannelId varchar(26) NOT NULL DEFAULT "";', - DECLARE AddChannelId BOOLEAN; - DECLARE AddChannelIdQuery TEXT DEFAULT NULL; - - -- 'CREATE INDEX idx_reactions_channel_id ON Reactions(ChannelId);' - DECLARE CreateIndex BOOLEAN; - DECLARE CreateIndexQuery TEXT DEFAULT NULL; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Reactions' - AND table_schema = DATABASE() - AND column_name = 'ChannelId' - INTO AddChannelId; - - SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Reactions' - AND table_schema = DATABASE() - AND index_name = 'idx_reactions_channel_id' - INTO CreateIndex; - - IF AddChannelId THEN - SET AddChannelIdQuery = 'ADD COLUMN ChannelId varchar(26) NOT NULL DEFAULT ""'; - END IF; - - IF CreateIndex THEN - SET CreateIndexQuery = 'ADD INDEX idx_reactions_channel_id (ChannelId)'; - END IF; - - SET @alterQuery = CONCAT_WS(', ', AddChannelIdQuery, CreateIndexQuery); - IF @alterQuery <> '' THEN - SET @query = CONCAT('ALTER TABLE Reactions ', @alterQuery); - PREPARE stmt FROM @query; - EXECUTE stmt; - DEALLOCATE PREPARE stmt; - END IF; - - UPDATE Reactions SET ChannelId = COALESCE((select ChannelId from Posts where Posts.Id = Reactions.PostId), '') WHERE ChannelId=""; -END// -DELIMITER ; -SELECT CONCAT('-- ', NOW(), ' MigrateReactions procedure starting.') AS DEBUG; -CALL MigrateReactions (); -SELECT CONCAT('-- ', NOW(), ' MigrateReactions procedure finished.') AS DEBUG; -DROP PROCEDURE IF EXISTS MigrateReactions; - -/* ==> mysql/000091_create_post_reminder.up.sql <== */ -CREATE TABLE IF NOT EXISTS PostReminders ( - PostId varchar(26) NOT NULL, - UserId varchar(26) NOT NULL, - TargetTime bigint, - INDEX idx_postreminders_targettime (TargetTime), - PRIMARY KEY (PostId, UserId) -); - -/* ==> mysql/000093_notify_admin.up.sql <== */ -CREATE TABLE IF NOT EXISTS NotifyAdmin ( - UserId varchar(26) NOT NULL, - CreateAt bigint(20) DEFAULT NULL, - RequiredPlan varchar(26) NOT NULL, - RequiredFeature varchar(100) NOT NULL, - Trial BOOLEAN NOT NULL, - PRIMARY KEY (UserId, RequiredFeature, RequiredPlan) -); - -/* ==> mysql/000094_threads_teamid.up.sql <== */ --- Replaced by 000096_threads_threadteamid.up.sql - -/* ==> mysql/000097_create_posts_priority.up.sql <== */ -CREATE TABLE IF NOT EXISTS PostsPriority ( - PostId varchar(26) NOT NULL, - ChannelId varchar(26) NOT NULL, - Priority varchar(32) NOT NULL, - RequestedAck tinyint(1), - PersistentNotifications tinyint(1), - PRIMARY KEY (PostId) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -/* ==> mysql/000098_create_post_acknowledgements.up.sql <== */ -CREATE TABLE IF NOT EXISTS PostAcknowledgements ( - PostId varchar(26) NOT NULL, - UserId varchar(26) NOT NULL, - AcknowledgedAt bigint(20) DEFAULT NULL, - PRIMARY KEY (PostId, UserId) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -/* ==> mysql/000099_create_drafts.up.sql <== */ -/* ==> mysql/000100_add_draft_priority_column.up.sql <== */ -CREATE TABLE IF NOT EXISTS Drafts ( - CreateAt bigint(20) DEFAULT NULL, - UpdateAt bigint(20) DEFAULT NULL, - DeleteAt bigint(20) DEFAULT NULL, - UserId varchar(26) NOT NULL, - ChannelId varchar(26) NOT NULL, - RootId varchar(26) DEFAULT '', - Message text, - Props text, - FileIds text, - Priority text, - PRIMARY KEY (UserId, ChannelId, RootId) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -/* ==> mysql/000101_create_true_up_review_history.up.sql <== */ -CREATE TABLE IF NOT EXISTS TrueUpReviewHistory ( - DueDate bigint(20), - Completed boolean, - PRIMARY KEY (DueDate) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/server/scripts/esrupgrades/esr.6.3-7.8.mysql.cleanup.sql b/server/scripts/esrupgrades/esr.6.3-7.8.mysql.cleanup.sql deleted file mode 100644 index 43af4c48445..00000000000 --- a/server/scripts/esrupgrades/esr.6.3-7.8.mysql.cleanup.sql +++ /dev/null @@ -1,168 +0,0 @@ -/* Product notices are controlled externally, via the mattermost/notices repository. - When there is a new notice specified there, the server may have time, right after - the migration and before it is shut down, to download it and modify the - ProductNoticeViewState table, adding a row for all users that have not seen it or - removing old notices that no longer need to be shown. This can happen in the - UpdateProductNotices function that is executed periodically to update the notices - cache. The script will never do this, so we need to remove all rows in that table - to avoid any unwanted diff. */ -DELETE FROM ProductNoticeViewState; - -/* Remove migration-related tables that are only updated through the server to track which - migrations have been applied */ -DROP TABLE IF EXISTS db_lock; -DROP TABLE IF EXISTS db_migrations; - -/* The security update check in the server may update the LastSecurityTime system value. To - avoid any spurious difference in the migrations, we update it to a fixed value. */ -UPDATE Systems SET Value = 1 WHERE Name = 'LastSecurityTime'; - -/* The server migration may contain a row in the Systems table marking the onboarding as complete. - There are no migrations related to this, so we can simply drop it here. */ -DELETE FROM Systems WHERE Name = 'FirstAdminSetupComplete'; - -/* The server migration contains an in-app migration that add playbooks permissions to certain roles: - getPlaybooksPermissionsAddManageRoles, defined in https://github.com/mattermost/mattermost-server/blob/56a093ceaee6389a01a35b6d4626ef5a9fea4759/app/permissions_migrations.go#L1056-L1072 - The specific roles ('%playbook%') are removed in the procedure below, but the migrations also add new rows to the Systems table marking the migrations as complete. - This in-app migration does not happen in the script, so we remove that rows here. */ -DELETE FROM Systems WHERE Name = 'playbooks_manage_roles'; - -/* The server migration contains an in-app migration that adds boards permissions to certain roles: - getProductsBoardsPermissions, defined in https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/app/permissions_migrations.go#L1074-L1093 - The specific roles (sysconsole_read_product_boards and sysconsole_write_product_boards) are removed in the procedure below, - but the migrations also adds a new row to the Systems table marking the migrations as complete. - This in-app migration does not happen in the script, so we remove that row here. */ -DELETE FROM Systems WHERE Name = 'products_boards'; - -/* The server migration contains an in-app migration that adds Ids to the Teams whose InviteId is an empty string: - doRemainingSchemaMigrations, defined in https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/app/migrations.go#L515-L540 - The migration is not replicated in the script, since it happens in-app, but the server adds a new row to the - Systems table marking the table as complete, which the script doesn't do, so we remove that row here. */ -DELETE FROM Systems WHERE Name = 'RemainingSchemaMigrations'; - -/* The server migration contains three in-app migration that adds a new role and new permissions - related to custom groups. The migrations are: - - doCustomGroupAdminRoleCreationMigration https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/app/migrations.go#L345-L469 - - getAddCustomUserGroupsPermissions https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/app/permissions_migrations.go#L974-L995 - - getAddCustomUserGroupsPermissionRestore https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/app/permissions_migrations.go#L997-L1019 - The specific roles and permissions are removed in the procedure below, but the migrations also - adds a new row to the Roles table for the new role and new rows to the Systems table marking the - migrations as complete. - This in-app migration does not happen in the script, so we remove that row here. */ -DELETE FROM Roles WHERE Name = 'system_custom_group_admin'; -DELETE FROM Systems WHERE Name = 'CustomGroupAdminRoleCreationMigrationComplete'; -DELETE FROM Systems WHERE Name = 'custom_groups_permissions'; -DELETE FROM Systems WHERE Name = 'custom_groups_permission_restore'; - -/* The server migration contains an in-app migration that updates the config, setting ServiceSettings.PostPriority - to true, doPostPriorityConfigDefaultTrueMigration, defined in https://github.com/mattermost/mattermost-server/blob/282bd351e3767dcfd8c8340da2e0915197c0dbcb/app/migrations.go#L542-L560 - The migration is not replicated in the script, since it happens in-app, but the server adds a new row to the - Systems table marking the table as complete, which the script doesn't do, so we remove that row here. */ -DELETE FROM Systems WHERE Name = 'PostPriorityConfigDefaultTrueMigrationComplete'; - -/* The rest of this script defines and executes a procedure to update the Roles table. It performs several changes: - 1. Set the UpdateAt column of all rows to a fixed value, so that the server migration changes to this column - do not appear in the diff. - 2. Remove the set of specific permissions added in the server migration that is not covered by the script, as - this logic happens all in-app after the normal DB migrations. - 3. Set a consistent order in the Permissions column, which is modelled a space-separated string containing each of - the different permissions each role has. This change is the reason why we need a complex procedure, which creates - a temporary table that pairs each single permission to its corresponding ID. So if the Roles table contains two - rows like: - Id: 'abcd' - Permissions: 'view_team read_public_channel invite_user' - Id: 'efgh' - Permissions: 'view_team create_emojis' - then the new temporary table will contain five rows like: - Id: 'abcd' - Permissions: 'view_team' - Id: 'abcd' - Permissions: 'read_public_channel' - Id: 'abcd' - Permissions: 'invite_user' - Id: 'efgh' - Permissions: 'view_team' - Id: 'efgh' - Permissions: 'create_emojis' -*/ - -DROP PROCEDURE IF EXISTS splitPermissions; -DROP PROCEDURE IF EXISTS sortAndFilterPermissionsInRoles; - -DROP TEMPORARY TABLE IF EXISTS temp_roles; -CREATE TEMPORARY TABLE temp_roles(id varchar(26), permission longtext); - -DELIMITER // - -/* Auxiliary procedure that splits the space-separated permissions string into single rows that are inserted - in the temporary temp_roles table along with their corresponding ID. */ -CREATE PROCEDURE splitPermissions( - IN id varchar(26), - IN permissionsString longtext -) -BEGIN - DECLARE idx INT DEFAULT 0; - SELECT TRIM(permissionsString) INTO permissionsString; - SELECT LOCATE(' ', permissionsString) INTO idx; - WHILE idx > 0 DO - INSERT INTO temp_roles SELECT id, TRIM(LEFT(permissionsString, idx)); - SELECT SUBSTR(permissionsString, idx+1) INTO permissionsString; - SELECT LOCATE(' ', permissionsString) INTO idx; - END WHILE; - INSERT INTO temp_roles(id, permission) VALUES(id, TRIM(permissionsString)); -END; // - -/* Main procedure that does update the Roles table */ -CREATE PROCEDURE sortAndFilterPermissionsInRoles() -BEGIN - DECLARE done INT DEFAULT FALSE; - DECLARE rolesId varchar(26) DEFAULT ''; - DECLARE rolesPermissions longtext DEFAULT ''; - DECLARE cur1 CURSOR FOR SELECT Id, Permissions FROM Roles; - DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; - - /* 1. Set a fixed value in the UpdateAt column for all rows in Roles table */ - UPDATE Roles SET UpdateAt = 1; - - /* Call splitPermissions for every row in the Roles table, thus populating the - temp_roles table. */ - OPEN cur1; - read_loop: LOOP - FETCH cur1 INTO rolesId, rolesPermissions; - IF done THEN - LEAVE read_loop; - END IF; - CALL splitPermissions(rolesId, rolesPermissions); - END LOOP; - CLOSE cur1; - - /* 2. Filter out the new permissions added by the in-app migrations */ - DELETE FROM temp_roles WHERE permission LIKE 'sysconsole_read_products_boards'; - DELETE FROM temp_roles WHERE permission LIKE 'sysconsole_write_products_boards'; - DELETE FROM temp_roles WHERE permission LIKE 'playbook_public_manage_roles'; - DELETE FROM temp_roles WHERE permission LIKE 'playbook_private_manage_roles'; - DELETE FROM temp_roles WHERE permission LIKE '%custom_group%'; - - /* Temporarily set to the maximum permitted value, since the call to group_concat - below needs a value bigger than the default */ - SET group_concat_max_len = 18446744073709551615; - - /* 3. Update the Permissions column in the Roles table with the filtered, sorted permissions, - concatenated again as a space-separated string */ - UPDATE - Roles INNER JOIN ( - SELECT temp_roles.id as Id, TRIM(group_concat(temp_roles.permission ORDER BY temp_roles.permission SEPARATOR ' ')) as Permissions - FROM Roles JOIN temp_roles ON Roles.Id = temp_roles.id - GROUP BY temp_roles.id - ) AS Sorted - ON Roles.Id = Sorted.Id - SET Roles.Permissions = Sorted.Permissions; - - /* Reset group_concat_max_len to its default value */ - SET group_concat_max_len = 1024; -END; // -DELIMITER ; - -CALL sortAndFilterPermissionsInRoles(); - -DROP TEMPORARY TABLE IF EXISTS temp_roles; diff --git a/server/scripts/esrupgrades/esr.6.3-7.8.mysql.up.sql b/server/scripts/esrupgrades/esr.6.3-7.8.mysql.up.sql deleted file mode 100644 index 572224e1a12..00000000000 --- a/server/scripts/esrupgrades/esr.6.3-7.8.mysql.up.sql +++ /dev/null @@ -1,599 +0,0 @@ -/* ==> mysql/000041_create_upload_sessions.up.sql <== */ -/* Release 5.37 was meant to contain the index idx_uploadsessions_type, but a bug prevented that. - This part of the migration #41 adds such index */ - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'UploadSessions' - AND table_schema = DATABASE() - AND index_name = 'idx_uploadsessions_type' - ) > 0, - 'SELECT 1', - 'CREATE INDEX idx_uploadsessions_type ON UploadSessions(Type);' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; - -/* ==> mysql/000075_alter_upload_sessions_index.up.sql <== */ -DELIMITER // -CREATE PROCEDURE AlterIndex() -BEGIN - DECLARE columnName varchar(26) default ''; - - SELECT IFNULL(GROUP_CONCAT(column_name ORDER BY seq_in_index), '') INTO columnName - FROM information_schema.statistics - WHERE table_schema = DATABASE() - AND table_name = 'UploadSessions' - AND index_name = 'idx_uploadsessions_user_id' - GROUP BY index_name; - - IF columnName = 'Type' THEN - DROP INDEX idx_uploadsessions_user_id ON UploadSessions; - CREATE INDEX idx_uploadsessions_user_id ON UploadSessions(UserId); - END IF; -END// -DELIMITER ; -CALL AlterIndex(); -DROP PROCEDURE IF EXISTS AlterIndex; - -/* ==> mysql/000076_upgrade_lastrootpostat.up.sql <== */ -DELIMITER // -CREATE PROCEDURE Migrate_LastRootPostAt_Default () -BEGIN - IF ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_NAME = 'Channels' - AND TABLE_SCHEMA = DATABASE() - AND COLUMN_NAME = 'LastRootPostAt' - AND (COLUMN_DEFAULT IS NULL OR COLUMN_DEFAULT != 0) - ) = 1 THEN - ALTER TABLE Channels ALTER COLUMN LastRootPostAt SET DEFAULT 0; - END IF; -END// -DELIMITER ; -CALL Migrate_LastRootPostAt_Default (); -DROP PROCEDURE IF EXISTS Migrate_LastRootPostAt_Default; - -DELIMITER // -CREATE PROCEDURE Migrate_LastRootPostAt_Fix () -BEGIN - IF ( - SELECT COUNT(*) - FROM Channels - WHERE LastRootPostAt IS NULL - ) > 0 THEN - -- fixes migrate cte and sets the LastRootPostAt for channels that don't have it set - UPDATE - Channels - INNER JOIN ( - SELECT - Channels.Id channelid, - COALESCE(MAX(Posts.CreateAt), 0) AS lastrootpost - FROM - Channels - LEFT JOIN Posts FORCE INDEX (idx_posts_channel_id_update_at) ON Channels.Id = Posts.ChannelId - WHERE - Posts.RootId = '' - GROUP BY - Channels.Id) AS q ON q.channelid = Channels.Id - SET - LastRootPostAt = lastrootpost - WHERE - LastRootPostAt IS NULL; - - -- sets LastRootPostAt to 0, for channels with no posts - UPDATE Channels SET LastRootPostAt=0 WHERE LastRootPostAt IS NULL; - END IF; -END// -DELIMITER ; -CALL Migrate_LastRootPostAt_Fix (); -DROP PROCEDURE IF EXISTS Migrate_LastRootPostAt_Fix; - -/* ==> mysql/000077_upgrade_users_v6.5.up.sql <== */ - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'AcceptedServiceTermsId' - ) > 0, - 'ALTER TABLE Users DROP COLUMN AcceptedServiceTermsId;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -/* ==> mysql/000078_create_oauth_mattermost_app_id.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'OAuthApps' - AND table_schema = DATABASE() - AND column_name = 'MattermostAppID' - ) > 0, - 'SELECT 1', - 'ALTER TABLE OAuthApps ADD COLUMN MattermostAppID varchar(32);' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -/* ==> mysql/000079_usergroups_displayname_index.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'UserGroups' - AND table_schema = DATABASE() - AND index_name = 'idx_usergroups_displayname' - ) > 0, - 'SELECT 1', - 'CREATE INDEX idx_usergroups_displayname ON UserGroups(DisplayName);' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; - -/* ==> mysql/000080_posts_createat_id.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Posts' - AND table_schema = DATABASE() - AND index_name = 'idx_posts_create_at_id' - ) > 0, - 'SELECT 1;', - 'CREATE INDEX idx_posts_create_at_id on Posts(CreateAt, Id) LOCK=NONE;' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; - -/* ==> mysql/000081_threads_deleteat.up.sql <== */ --- Replaced by 000083_threads_threaddeleteat.up.sql - -/* ==> mysql/000082_upgrade_oauth_mattermost_app_id.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'OAuthApps' - AND table_schema = DATABASE() - AND column_name = 'MattermostAppID' - ) > 0, - 'UPDATE OAuthApps SET MattermostAppID = "" WHERE MattermostAppID IS NULL;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'OAuthApps' - AND table_schema = DATABASE() - AND column_name = 'MattermostAppID' - ) > 0, - 'ALTER TABLE OAuthApps MODIFY MattermostAppID varchar(32) NOT NULL DEFAULT "";', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -/* ==> mysql/000083_threads_threaddeleteat.up.sql <== */ --- Drop any existing DeleteAt column from 000081_threads_deleteat.up.sql -SET @preparedStatement = (SELECT IF( - EXISTS( - SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Threads' - AND table_schema = DATABASE() - AND column_name = 'DeleteAt' - ) > 0, - 'ALTER TABLE Threads DROP COLUMN DeleteAt;', - 'SELECT 1;' -)); - -PREPARE removeColumnIfExists FROM @preparedStatement; -EXECUTE removeColumnIfExists; -DEALLOCATE PREPARE removeColumnIfExists; - -SET @preparedStatement = (SELECT IF( - NOT EXISTS( - SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Threads' - AND table_schema = DATABASE() - AND column_name = 'ThreadDeleteAt' - ), - 'ALTER TABLE Threads ADD COLUMN ThreadDeleteAt bigint(20);', - 'SELECT 1;' -)); - -PREPARE addColumnIfNotExists FROM @preparedStatement; -EXECUTE addColumnIfNotExists; -DEALLOCATE PREPARE addColumnIfNotExists; - -UPDATE Threads, Posts -SET Threads.ThreadDeleteAt = Posts.DeleteAt -WHERE Posts.Id = Threads.PostId -AND Threads.ThreadDeleteAt IS NULL; - -/* ==> mysql/000084_recent_searches.up.sql <== */ -CREATE TABLE IF NOT EXISTS RecentSearches ( - UserId CHAR(26), - SearchPointer int, - Query json, - CreateAt bigint NOT NULL, - PRIMARY KEY (UserId, SearchPointer) -); -/* ==> mysql/000085_fileinfo_add_archived_column.up.sql <== */ - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'FileInfo' - AND table_schema = DATABASE() - AND column_name = 'Archived' - ) > 0, - 'SELECT 1', - 'ALTER TABLE FileInfo ADD COLUMN Archived boolean NOT NULL DEFAULT false;' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -/* ==> mysql/000086_add_cloud_limits_archived.up.sql <== */ -SET @preparedStatement = (SELECT IF( - NOT EXISTS( - SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Teams' - AND table_schema = DATABASE() - AND column_name = 'CloudLimitsArchived' - ), - 'ALTER TABLE Teams ADD COLUMN CloudLimitsArchived BOOLEAN NOT NULL DEFAULT FALSE;', - 'SELECT 1' -)); - -PREPARE alterIfNotExists FROM @preparedStatement; -EXECUTE alterIfNotExists; -DEALLOCATE PREPARE alterIfNotExists; - -/* ==> mysql/000087_sidebar_categories_index.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'SidebarCategories' - AND table_schema = DATABASE() - AND index_name = 'idx_sidebarcategories_userid_teamid' - ) > 0, - 'SELECT 1;', - 'CREATE INDEX idx_sidebarcategories_userid_teamid on SidebarCategories(UserId, TeamId) LOCK=NONE;' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; - -/* ==> mysql/000088_remaining_migrations.up.sql <== */ -DROP TABLE IF EXISTS JobStatuses; - -DROP TABLE IF EXISTS PasswordRecovery; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'ThemeProps' - ) > 0, - 'INSERT INTO Preferences(UserId, Category, Name, Value) SELECT Id, \'\', \'\', ThemeProps FROM Users WHERE Users.ThemeProps != \'null\'', - 'SELECT 1' -)); - -PREPARE migrateTheme FROM @preparedStatement; -EXECUTE migrateTheme; -DEALLOCATE PREPARE migrateTheme; - --- We have to do this twice because the prepared statement doesn't support multiple SQL queries --- in a single string. - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Users' - AND table_schema = DATABASE() - AND column_name = 'ThemeProps' - ) > 0, - 'ALTER TABLE Users DROP COLUMN ThemeProps', - 'SELECT 1' -)); - -PREPARE migrateTheme FROM @preparedStatement; -EXECUTE migrateTheme; -DEALLOCATE PREPARE migrateTheme; - -/* ==> mysql/000089_add-channelid-to-reaction.up.sql <== */ -SET @preparedStatement = (SELECT IF( - NOT EXISTS( - SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Reactions' - AND table_schema = DATABASE() - AND column_name = 'ChannelId' - ), - 'ALTER TABLE Reactions ADD COLUMN ChannelId varchar(26) NOT NULL DEFAULT "";', - 'SELECT 1;' -)); - -PREPARE addColumnIfNotExists FROM @preparedStatement; -EXECUTE addColumnIfNotExists; -DEALLOCATE PREPARE addColumnIfNotExists; - - -UPDATE Reactions SET ChannelId = COALESCE((select ChannelId from Posts where Posts.Id = Reactions.PostId), '') WHERE ChannelId=""; - - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Reactions' - AND table_schema = DATABASE() - AND index_name = 'idx_reactions_channel_id' - ) > 0, - 'SELECT 1', - 'CREATE INDEX idx_reactions_channel_id ON Reactions(ChannelId);' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; - -/* ==> mysql/000090_create_enums.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Channels' - AND table_schema = DATABASE() - AND column_name = 'Type' - AND column_type != 'ENUM("D", "O", "G", "P")' - ) > 0, - 'ALTER TABLE Channels MODIFY COLUMN Type ENUM("D", "O", "G", "P");', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Teams' - AND table_schema = DATABASE() - AND column_name = 'Type' - AND column_type != 'ENUM("I", "O")' - ) > 0, - 'ALTER TABLE Teams MODIFY COLUMN Type ENUM("I", "O");', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'UploadSessions' - AND table_schema = DATABASE() - AND column_name = 'Type' - AND column_type != 'ENUM("attachment", "import")' - ) > 0, - 'ALTER TABLE UploadSessions MODIFY COLUMN Type ENUM("attachment", "import");', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; -/* ==> mysql/000091_create_post_reminder.up.sql <== */ -CREATE TABLE IF NOT EXISTS PostReminders ( - PostId varchar(26) NOT NULL, - UserId varchar(26) NOT NULL, - TargetTime bigint, - PRIMARY KEY (PostId, UserId) -); - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'PostReminders' - AND table_schema = DATABASE() - AND index_name = 'idx_postreminders_targettime' - ) > 0, - 'SELECT 1', - 'CREATE INDEX idx_postreminders_targettime ON PostReminders(TargetTime);' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; -/* ==> mysql/000092_add_createat_to_teammembers.up.sql <== */ -SET @preparedStatement = (SELECT IF( - NOT EXISTS( - SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'TeamMembers' - AND table_schema = DATABASE() - AND column_name = 'CreateAt' - ), - 'ALTER TABLE TeamMembers ADD COLUMN CreateAt bigint DEFAULT 0;', - 'SELECT 1;' -)); - -PREPARE addColumnIfNotExists FROM @preparedStatement; -EXECUTE addColumnIfNotExists; -DEALLOCATE PREPARE addColumnIfNotExists; - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'TeamMembers' - AND table_schema = DATABASE() - AND index_name = 'idx_teammembers_createat' - ) > 0, - 'SELECT 1', - 'CREATE INDEX idx_teammembers_createat ON TeamMembers(CreateAt);' -)); - -PREPARE createIndexIfNotExists FROM @preparedStatement; -EXECUTE createIndexIfNotExists; -DEALLOCATE PREPARE createIndexIfNotExists; - -/* ==> mysql/000093_notify_admin.up.sql <== */ -CREATE TABLE IF NOT EXISTS NotifyAdmin ( - UserId varchar(26) NOT NULL, - CreateAt bigint(20) DEFAULT NULL, - RequiredPlan varchar(26) NOT NULL, - RequiredFeature varchar(100) NOT NULL, - Trial BOOLEAN NOT NULL, - PRIMARY KEY (UserId, RequiredFeature, RequiredPlan) -); - -/* ==> mysql/000094_threads_teamid.up.sql <== */ --- Replaced by 000096_threads_threadteamid.up.sql - -/* ==> mysql/000095_remove_posts_parentid.up.sql <== */ --- While upgrading from 5.x to 6.x with manual queries, there is a chance that this --- migration is skipped. In that case, we need to make sure that the column is dropped. - -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Posts' - AND table_schema = DATABASE() - AND column_name = 'ParentId' - ) > 0, - 'ALTER TABLE Posts DROP COLUMN ParentId;', - 'SELECT 1' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -/* ==> mysql/000096_threads_threadteamid.up.sql <== */ --- Drop any existing TeamId column from 000094_threads_teamid.up.sql -SET @preparedStatement = (SELECT IF( - EXISTS( - SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS - WHERE table_name = 'Threads' - AND table_schema = DATABASE() - AND column_name = 'TeamId' - ) > 0, - 'ALTER TABLE Threads DROP COLUMN TeamId;', - 'SELECT 1;' -)); - -PREPARE removeColumnIfExists FROM @preparedStatement; -EXECUTE removeColumnIfExists; -DEALLOCATE PREPARE removeColumnIfExists; - -SET @preparedStatement = (SELECT IF( - NOT EXISTS( - SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Threads' - AND table_schema = DATABASE() - AND column_name = 'ThreadTeamId' - ), - 'ALTER TABLE Threads ADD COLUMN ThreadTeamId varchar(26) DEFAULT NULL;', - 'SELECT 1;' -)); - -PREPARE addColumnIfNotExists FROM @preparedStatement; -EXECUTE addColumnIfNotExists; -DEALLOCATE PREPARE addColumnIfNotExists; - -UPDATE Threads, Channels -SET Threads.ThreadTeamId = Channels.TeamId -WHERE Channels.Id = Threads.ChannelId -AND Threads.ThreadTeamId IS NULL; - -/* ==> mysql/000097_create_posts_priority.up.sql <== */ -CREATE TABLE IF NOT EXISTS PostsPriority ( - PostId varchar(26) NOT NULL, - ChannelId varchar(26) NOT NULL, - Priority varchar(32) NOT NULL, - RequestedAck tinyint(1), - PersistentNotifications tinyint(1), - PRIMARY KEY (PostId) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -SET @preparedStatement = (SELECT IF( - NOT EXISTS( - SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'ChannelMembers' - AND table_schema = DATABASE() - AND column_name = 'UrgentMentionCount' - ), - 'ALTER TABLE ChannelMembers ADD COLUMN UrgentMentionCount bigint(20);', - 'SELECT 1;' -)); - -PREPARE alterIfNotExists FROM @preparedStatement; -EXECUTE alterIfNotExists; -DEALLOCATE PREPARE alterIfNotExists; - -/* ==> mysql/000098_create_post_acknowledgements.up.sql <== */ -CREATE TABLE IF NOT EXISTS PostAcknowledgements ( - PostId varchar(26) NOT NULL, - UserId varchar(26) NOT NULL, - AcknowledgedAt bigint(20) DEFAULT NULL, - PRIMARY KEY (PostId, UserId) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -/* ==> mysql/000099_create_drafts.up.sql <== */ -CREATE TABLE IF NOT EXISTS Drafts ( - CreateAt bigint(20) DEFAULT NULL, - UpdateAt bigint(20) DEFAULT NULL, - DeleteAt bigint(20) DEFAULT NULL, - UserId varchar(26) NOT NULL, - ChannelId varchar(26) NOT NULL, - RootId varchar(26) DEFAULT '', - Message text, - Props text, - FileIds text, - PRIMARY KEY (UserId, ChannelId, RootId) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -/* ==> mysql/000100_add_draft_priority_column.up.sql <== */ -SET @preparedStatement = (SELECT IF( - ( - SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'Drafts' - AND table_schema = DATABASE() - AND column_name = 'Priority' - ) > 0, - 'SELECT 1', - 'ALTER TABLE Drafts ADD COLUMN Priority text;' -)); - -PREPARE alterIfExists FROM @preparedStatement; -EXECUTE alterIfExists; -DEALLOCATE PREPARE alterIfExists; - -/* ==> mysql/000101_create_true_up_review_history.up.sql <== */ -CREATE TABLE IF NOT EXISTS TrueUpReviewHistory ( - DueDate bigint(20), - Completed boolean, - PRIMARY KEY (DueDate) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/server/scripts/esrupgrades/esr.common.mysql.preprocess.sql b/server/scripts/esrupgrades/esr.common.mysql.preprocess.sql deleted file mode 100644 index 4c06e1ba19a..00000000000 --- a/server/scripts/esrupgrades/esr.common.mysql.preprocess.sql +++ /dev/null @@ -1,23 +0,0 @@ -/* The sessions in the DB dump may have expired before the CI tests run, making - the server remove the rows and generating a spurious diff that we want to avoid. - In order to do so, we mark all sessions' ExpiresAt value to 0, so they never expire. */ -UPDATE Sessions SET ExpiresAt = 0; - -/* The dump may not contain a system-bot user, in which case the server will create - one if it's not shutdown before a job requests it. This situation creates a flaky - tests in which, in rare ocassions, the system-bot is indeed created, generating a - spurious diff. We avoid this by making sure that there is a system-bot user and - corresponding bot */ -DELIMITER // -CREATE PROCEDURE AddSystemBotIfNeeded () -BEGIN - DECLARE CreateSystemBot BOOLEAN; - SELECT COUNT(*) = 0 FROM Users WHERE Username = 'system-bot' INTO CreateSystemBot; - IF CreateSystemBot THEN - /* These values are retrieved from a real system-bot created by a server */ - INSERT INTO `Bots` VALUES ('nc7y5x1i8jgr9btabqo5m3579c','','phxrtijfrtfg7k4bwj9nophqyc',0,1681308600015,1681308600015,0); - INSERT INTO `Users` VALUES ('nc7y5x1i8jgr9btabqo5m3579c',1681308600014,1681308600014,0,'system-bot','',NULL,'','system-bot@localhost',0,'','System','','','system_user',0,'{}','{\"push\": \"mention\", \"email\": \"true\", \"channel\": \"true\", \"desktop\": \"mention\", \"comments\": \"never\", \"first_name\": \"false\", \"push_status\": \"away\", \"mention_keys\": \"\", \"push_threads\": \"all\", \"desktop_sound\": \"true\", \"email_threads\": \"all\", \"desktop_threads\": \"all\"}',1681308600014,0,0,'en','{\"manualTimezone\": \"\", \"automaticTimezone\": \"\", \"useAutomaticTimezone\": \"true\"}',0,'',NULL); - END IF; -END// -DELIMITER ; -CALL AddSystemBotIfNeeded(); diff --git a/server/scripts/mattermost-mysql-5.0.0.sql b/server/scripts/mattermost-mysql-5.0.0.sql deleted file mode 100644 index 9d2c30ba568..00000000000 --- a/server/scripts/mattermost-mysql-5.0.0.sql +++ /dev/null @@ -1,1057 +0,0 @@ --- MySQL dump 10.13 Distrib 5.7.25, for Linux (x86_64) --- --- Host: 127.0.0.1 Database: mattermost_test --- ------------------------------------------------------ --- Server version 5.7.23 - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - --- --- Table structure for table `Audits` --- - -DROP TABLE IF EXISTS `Audits`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Audits` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `Action` text, - `ExtraInfo` text, - `IpAddress` varchar(64) DEFAULT NULL, - `SessionId` varchar(26) DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `idx_audits_user_id` (`UserId`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Audits` --- - -LOCK TABLES `Audits` WRITE; -/*!40000 ALTER TABLE `Audits` DISABLE KEYS */; -/*!40000 ALTER TABLE `Audits` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `ChannelMemberHistory` --- - -DROP TABLE IF EXISTS `ChannelMemberHistory`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `ChannelMemberHistory` ( - `ChannelId` varchar(26) NOT NULL, - `UserId` varchar(26) NOT NULL, - `JoinTime` bigint(20) NOT NULL, - `LeaveTime` bigint(20) DEFAULT NULL, - PRIMARY KEY (`ChannelId`,`UserId`,`JoinTime`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `ChannelMemberHistory` --- - -LOCK TABLES `ChannelMemberHistory` WRITE; -/*!40000 ALTER TABLE `ChannelMemberHistory` DISABLE KEYS */; -/*!40000 ALTER TABLE `ChannelMemberHistory` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `ChannelMembers` --- - -DROP TABLE IF EXISTS `ChannelMembers`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `ChannelMembers` ( - `ChannelId` varchar(26) NOT NULL, - `UserId` varchar(26) NOT NULL, - `Roles` varchar(64) DEFAULT NULL, - `LastViewedAt` bigint(20) DEFAULT NULL, - `MsgCount` bigint(20) DEFAULT NULL, - `MentionCount` bigint(20) DEFAULT NULL, - `NotifyProps` text, - `LastUpdateAt` bigint(20) DEFAULT NULL, - `SchemeUser` tinyint(4) DEFAULT NULL, - `SchemeAdmin` tinyint(4) DEFAULT NULL, - PRIMARY KEY (`ChannelId`,`UserId`), - KEY `idx_channelmembers_channel_id` (`ChannelId`), - KEY `idx_channelmembers_user_id` (`UserId`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `ChannelMembers` --- - -LOCK TABLES `ChannelMembers` WRITE; -/*!40000 ALTER TABLE `ChannelMembers` DISABLE KEYS */; -/*!40000 ALTER TABLE `ChannelMembers` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Channels` --- - -DROP TABLE IF EXISTS `Channels`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Channels` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `TeamId` varchar(26) DEFAULT NULL, - `Type` varchar(1) DEFAULT NULL, - `DisplayName` varchar(64) DEFAULT NULL, - `Name` varchar(64) DEFAULT NULL, - `Header` text, - `Purpose` varchar(250) DEFAULT NULL, - `LastPostAt` bigint(20) DEFAULT NULL, - `TotalMsgCount` bigint(20) DEFAULT NULL, - `ExtraUpdateAt` bigint(20) DEFAULT NULL, - `CreatorId` varchar(26) DEFAULT NULL, - `SchemeId` varchar(26) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `Name` (`Name`,`TeamId`), - KEY `idx_channels_team_id` (`TeamId`), - KEY `idx_channels_name` (`Name`), - KEY `idx_channels_update_at` (`UpdateAt`), - KEY `idx_channels_create_at` (`CreateAt`), - KEY `idx_channels_delete_at` (`DeleteAt`), - FULLTEXT KEY `idx_channels_txt` (`Name`,`DisplayName`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Channels` --- - -LOCK TABLES `Channels` WRITE; -/*!40000 ALTER TABLE `Channels` DISABLE KEYS */; -/*!40000 ALTER TABLE `Channels` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `ClusterDiscovery` --- - -DROP TABLE IF EXISTS `ClusterDiscovery`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `ClusterDiscovery` ( - `Id` varchar(26) NOT NULL, - `Type` varchar(64) DEFAULT NULL, - `ClusterName` varchar(64) DEFAULT NULL, - `Hostname` text, - `GossipPort` int(11) DEFAULT NULL, - `Port` int(11) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `LastPingAt` bigint(20) DEFAULT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `ClusterDiscovery` --- - -LOCK TABLES `ClusterDiscovery` WRITE; -/*!40000 ALTER TABLE `ClusterDiscovery` DISABLE KEYS */; -/*!40000 ALTER TABLE `ClusterDiscovery` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `CommandWebhooks` --- - -DROP TABLE IF EXISTS `CommandWebhooks`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `CommandWebhooks` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `CommandId` varchar(26) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `ChannelId` varchar(26) DEFAULT NULL, - `RootId` varchar(26) DEFAULT NULL, - `ParentId` varchar(26) DEFAULT NULL, - `UseCount` int(11) DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `idx_command_webhook_create_at` (`CreateAt`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `CommandWebhooks` --- - -LOCK TABLES `CommandWebhooks` WRITE; -/*!40000 ALTER TABLE `CommandWebhooks` DISABLE KEYS */; -/*!40000 ALTER TABLE `CommandWebhooks` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Commands` --- - -DROP TABLE IF EXISTS `Commands`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Commands` ( - `Id` varchar(26) NOT NULL, - `Token` varchar(26) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `CreatorId` varchar(26) DEFAULT NULL, - `TeamId` varchar(26) DEFAULT NULL, - `Trigger` varchar(128) DEFAULT NULL, - `Method` varchar(1) DEFAULT NULL, - `Username` varchar(64) DEFAULT NULL, - `IconURL` text, - `AutoComplete` tinyint(1) DEFAULT NULL, - `AutoCompleteDesc` text, - `AutoCompleteHint` text, - `DisplayName` varchar(64) DEFAULT NULL, - `Description` varchar(128) DEFAULT NULL, - `URL` text, - PRIMARY KEY (`Id`), - KEY `idx_command_team_id` (`TeamId`), - KEY `idx_command_update_at` (`UpdateAt`), - KEY `idx_command_create_at` (`CreateAt`), - KEY `idx_command_delete_at` (`DeleteAt`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Commands` --- - -LOCK TABLES `Commands` WRITE; -/*!40000 ALTER TABLE `Commands` DISABLE KEYS */; -/*!40000 ALTER TABLE `Commands` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Compliances` --- - -DROP TABLE IF EXISTS `Compliances`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Compliances` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `Status` varchar(64) DEFAULT NULL, - `Count` int(11) DEFAULT NULL, - `Desc` text, - `Type` varchar(64) DEFAULT NULL, - `StartAt` bigint(20) DEFAULT NULL, - `EndAt` bigint(20) DEFAULT NULL, - `Keywords` text, - `Emails` text, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Compliances` --- - -LOCK TABLES `Compliances` WRITE; -/*!40000 ALTER TABLE `Compliances` DISABLE KEYS */; -/*!40000 ALTER TABLE `Compliances` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Emoji` --- - -DROP TABLE IF EXISTS `Emoji`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Emoji` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `CreatorId` varchar(26) DEFAULT NULL, - `Name` varchar(64) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `Name` (`Name`,`DeleteAt`), - KEY `idx_emoji_update_at` (`UpdateAt`), - KEY `idx_emoji_create_at` (`CreateAt`), - KEY `idx_emoji_delete_at` (`DeleteAt`), - KEY `idx_emoji_name` (`Name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Emoji` --- - -LOCK TABLES `Emoji` WRITE; -/*!40000 ALTER TABLE `Emoji` DISABLE KEYS */; -/*!40000 ALTER TABLE `Emoji` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `FileInfo` --- - -DROP TABLE IF EXISTS `FileInfo`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `FileInfo` ( - `Id` varchar(26) NOT NULL, - `CreatorId` varchar(26) DEFAULT NULL, - `PostId` varchar(26) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `Path` text, - `ThumbnailPath` text, - `PreviewPath` text, - `Name` text, - `Extension` varchar(64) DEFAULT NULL, - `Size` bigint(20) DEFAULT NULL, - `MimeType` text, - `Width` int(11) DEFAULT NULL, - `Height` int(11) DEFAULT NULL, - `HasPreviewImage` tinyint(1) DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `idx_fileinfo_update_at` (`UpdateAt`), - KEY `idx_fileinfo_create_at` (`CreateAt`), - KEY `idx_fileinfo_delete_at` (`DeleteAt`), - KEY `idx_fileinfo_postid_at` (`PostId`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `FileInfo` --- - -LOCK TABLES `FileInfo` WRITE; -/*!40000 ALTER TABLE `FileInfo` DISABLE KEYS */; -/*!40000 ALTER TABLE `FileInfo` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `IncomingWebhooks` --- - -DROP TABLE IF EXISTS `IncomingWebhooks`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `IncomingWebhooks` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `ChannelId` varchar(26) DEFAULT NULL, - `TeamId` varchar(26) DEFAULT NULL, - `DisplayName` varchar(64) DEFAULT NULL, - `Description` text, - `Username` varchar(255) DEFAULT NULL, - `IconURL` text, - `ChannelLocked` tinyint(1) DEFAULT 0, - PRIMARY KEY (`Id`), - KEY `idx_incoming_webhook_user_id` (`UserId`), - KEY `idx_incoming_webhook_team_id` (`TeamId`), - KEY `idx_incoming_webhook_update_at` (`UpdateAt`), - KEY `idx_incoming_webhook_create_at` (`CreateAt`), - KEY `idx_incoming_webhook_delete_at` (`DeleteAt`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `IncomingWebhooks` --- - -LOCK TABLES `IncomingWebhooks` WRITE; -/*!40000 ALTER TABLE `IncomingWebhooks` DISABLE KEYS */; -/*!40000 ALTER TABLE `IncomingWebhooks` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Jobs` --- - -DROP TABLE IF EXISTS `Jobs`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Jobs` ( - `Id` varchar(26) NOT NULL, - `Type` varchar(32) DEFAULT NULL, - `Priority` bigint(20) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `StartAt` bigint(20) DEFAULT NULL, - `LastActivityAt` bigint(20) DEFAULT NULL, - `Status` varchar(32) DEFAULT NULL, - `Progress` bigint(20) DEFAULT NULL, - `Data` text, - PRIMARY KEY (`Id`), - KEY `idx_jobs_type` (`Type`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Jobs` --- - -LOCK TABLES `Jobs` WRITE; -/*!40000 ALTER TABLE `Jobs` DISABLE KEYS */; -/*!40000 ALTER TABLE `Jobs` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Licenses` --- - -DROP TABLE IF EXISTS `Licenses`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Licenses` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `Bytes` text, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Licenses` --- - -LOCK TABLES `Licenses` WRITE; -/*!40000 ALTER TABLE `Licenses` DISABLE KEYS */; -/*!40000 ALTER TABLE `Licenses` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `OAuthAccessData` --- - -DROP TABLE IF EXISTS `OAuthAccessData`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `OAuthAccessData` ( - `Token` varchar(26) NOT NULL, - `RefreshToken` varchar(26) DEFAULT NULL, - `RedirectUri` text, - `ClientId` varchar(26) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `ExpiresAt` bigint(20) DEFAULT '0', - `Scope` varchar(128) DEFAULT 'user', - PRIMARY KEY (`Token`), - UNIQUE KEY `ClientId` (`ClientId`,`UserId`), - KEY `idx_oauthaccessdata_client_id` (`ClientId`), - KEY `idx_oauthaccessdata_user_id` (`UserId`), - KEY `idx_oauthaccessdata_refresh_token` (`RefreshToken`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `OAuthAccessData` --- - -LOCK TABLES `OAuthAccessData` WRITE; -/*!40000 ALTER TABLE `OAuthAccessData` DISABLE KEYS */; -/*!40000 ALTER TABLE `OAuthAccessData` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `OAuthApps` --- - -DROP TABLE IF EXISTS `OAuthApps`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `OAuthApps` ( - `Id` varchar(26) NOT NULL, - `CreatorId` varchar(26) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `ClientSecret` varchar(128) DEFAULT NULL, - `Name` varchar(64) DEFAULT NULL, - `Description` text, - `CallbackUrls` text, - `Homepage` text, - `IsTrusted` tinyint(1) DEFAULT '0', - `IconURL` varchar(512) DEFAULT '', - PRIMARY KEY (`Id`), - KEY `idx_oauthapps_creator_id` (`CreatorId`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `OAuthApps` --- - -LOCK TABLES `OAuthApps` WRITE; -/*!40000 ALTER TABLE `OAuthApps` DISABLE KEYS */; -/*!40000 ALTER TABLE `OAuthApps` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `OAuthAuthData` --- - -DROP TABLE IF EXISTS `OAuthAuthData`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `OAuthAuthData` ( - `ClientId` varchar(26) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `Code` varchar(128) NOT NULL, - `ExpiresIn` int(11) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `RedirectUri` text, - `State` text, - `Scope` varchar(128) DEFAULT NULL, - PRIMARY KEY (`Code`), - KEY `idx_oauthauthdata_client_id` (`Code`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `OAuthAuthData` --- - -LOCK TABLES `OAuthAuthData` WRITE; -/*!40000 ALTER TABLE `OAuthAuthData` DISABLE KEYS */; -/*!40000 ALTER TABLE `OAuthAuthData` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `OutgoingWebhooks` --- - -DROP TABLE IF EXISTS `OutgoingWebhooks`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `OutgoingWebhooks` ( - `Id` varchar(26) NOT NULL, - `Token` varchar(26) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `CreatorId` varchar(26) DEFAULT NULL, - `ChannelId` varchar(26) DEFAULT NULL, - `TeamId` varchar(26) DEFAULT NULL, - `TriggerWords` text, - `CallbackURLs` text, - `DisplayName` varchar(64) DEFAULT NULL, - `ContentType` varchar(128) DEFAULT NULL, - `TriggerWhen` int(11) DEFAULT '0', - `Username` varchar(64) DEFAULT NULL, - `IconURL` text, - `Description` text(128), - PRIMARY KEY (`Id`), - KEY `idx_outgoing_webhook_team_id` (`TeamId`), - KEY `idx_outgoing_webhook_update_at` (`UpdateAt`), - KEY `idx_outgoing_webhook_create_at` (`CreateAt`), - KEY `idx_outgoing_webhook_delete_at` (`DeleteAt`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `OutgoingWebhooks` --- - -LOCK TABLES `OutgoingWebhooks` WRITE; -/*!40000 ALTER TABLE `OutgoingWebhooks` DISABLE KEYS */; -/*!40000 ALTER TABLE `OutgoingWebhooks` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `PluginKeyValueStore` --- - -DROP TABLE IF EXISTS `PluginKeyValueStore`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `PluginKeyValueStore` ( - `PluginId` varchar(190) NOT NULL, - `PKey` varchar(50) NOT NULL, - `PValue` mediumblob, - PRIMARY KEY (`PluginId`,`PKey`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `PluginKeyValueStore` --- - -LOCK TABLES `PluginKeyValueStore` WRITE; -/*!40000 ALTER TABLE `PluginKeyValueStore` DISABLE KEYS */; -/*!40000 ALTER TABLE `PluginKeyValueStore` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Posts` --- - -DROP TABLE IF EXISTS `Posts`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Posts` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `ChannelId` varchar(26) DEFAULT NULL, - `RootId` varchar(26) DEFAULT NULL, - `ParentId` varchar(26) DEFAULT NULL, - `OriginalId` varchar(26) DEFAULT NULL, - `Message` text, - `Type` varchar(26) DEFAULT NULL, - `Props` text, - `Hashtags` text, - `Filenames` text, - `FileIds` text, - `HasReactions` tinyint(1) DEFAULT '0', - `EditAt` bigint(20) DEFAULT '0', - `IsPinned` tinyint(1) DEFAULT '0', - PRIMARY KEY (`Id`), - KEY `idx_posts_update_at` (`UpdateAt`), - KEY `idx_posts_create_at` (`CreateAt`), - KEY `idx_posts_delete_at` (`DeleteAt`), - KEY `idx_posts_channel_id` (`ChannelId`), - KEY `idx_posts_root_id` (`RootId`), - KEY `idx_posts_user_id` (`UserId`), - KEY `idx_posts_is_pinned` (`IsPinned`), - KEY `idx_posts_channel_id_update_at` (`ChannelId`,`UpdateAt`), - KEY `idx_posts_channel_id_delete_at_create_at` (`ChannelId`,`DeleteAt`,`CreateAt`), - FULLTEXT KEY `idx_posts_message_txt` (`Message`), - FULLTEXT KEY `idx_posts_hashtags_txt` (`Hashtags`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Posts` --- - -LOCK TABLES `Posts` WRITE; -/*!40000 ALTER TABLE `Posts` DISABLE KEYS */; -/*!40000 ALTER TABLE `Posts` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Preferences` --- - -DROP TABLE IF EXISTS `Preferences`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Preferences` ( - `UserId` varchar(26) NOT NULL, - `Category` varchar(32) NOT NULL, - `Name` varchar(32) NOT NULL, - `Value` text, - PRIMARY KEY (`UserId`,`Category`,`Name`), - KEY `idx_preferences_user_id` (`UserId`), - KEY `idx_preferences_category` (`Category`), - KEY `idx_preferences_name` (`Name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Preferences` --- - -LOCK TABLES `Preferences` WRITE; -/*!40000 ALTER TABLE `Preferences` DISABLE KEYS */; -/*!40000 ALTER TABLE `Preferences` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Reactions` --- - -DROP TABLE IF EXISTS `Reactions`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Reactions` ( - `UserId` varchar(26) NOT NULL, - `PostId` varchar(26) NOT NULL, - `EmojiName` varchar(64) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - PRIMARY KEY (`PostId`,`UserId`,`EmojiName`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Reactions` --- - -LOCK TABLES `Reactions` WRITE; -/*!40000 ALTER TABLE `Reactions` DISABLE KEYS */; -/*!40000 ALTER TABLE `Reactions` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Roles` --- - -DROP TABLE IF EXISTS `Roles`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Roles` ( - `Id` varchar(26) NOT NULL, - `Name` varchar(64) DEFAULT NULL, - `DisplayName` varchar(128) DEFAULT NULL, - `Description` text, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `Permissions` text, - `SchemeManaged` tinyint(1) DEFAULT NULL, - `BuiltIn` tinyint(1) DEFAULT '0', - PRIMARY KEY (`Id`), - UNIQUE KEY `Name` (`Name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Roles` --- - -LOCK TABLES `Roles` WRITE; -/*!40000 ALTER TABLE `Roles` DISABLE KEYS */; -INSERT INTO `Roles` VALUES ('1x1ypn6zwbrubc3i7urg1qc4hr','team_user','authentication.roles.team_user.name','authentication.roles.team_user.description',1552023386683,1552023386683,0,' list_team_channels join_public_channels read_public_channel view_team create_public_channel manage_public_channel_properties delete_public_channel create_private_channel manage_private_channel_properties delete_private_channel invite_user add_user_to_team',1,1),('9ro6s3aiffbomdsm1dszr1gxec','team_post_all','authentication.roles.team_post_all.name','authentication.roles.team_post_all.description',1552023386717,1552023386717,0,' create_post',0,1),('api7kwbqwjbrtp8b5zq1d5ot8w','system_user_access_token','authentication.roles.system_user_access_token.name','authentication.roles.system_user_access_token.description',1552023386784,1552023386784,0,' create_user_access_token read_user_access_token revoke_user_access_token',0,1),('b5hwuid8ofdb9eoca1skzepmoy','team_post_all_public','authentication.roles.team_post_all_public.name','authentication.roles.team_post_all_public.description',1552023386184,1552023386184,0,' create_post_public',0,1),('j79gy46igfrztkyihuqm38h51y','system_user','authentication.roles.global_user.name','authentication.roles.global_user.description',1552023386370,1552023386918,0,' create_direct_channel create_group_channel permanent_delete_user create_team manage_emojis',1,1),('miqk4yzctbyoxg8ye3sbfuoa9y','channel_user','authentication.roles.channel_user.name','authentication.roles.channel_user.description',1552023386587,1552023386587,0,' read_channel add_reaction remove_reaction manage_public_channel_members upload_file get_public_link create_post use_slash_commands manage_private_channel_members delete_post edit_post',1,1),('myf6w6mm5pbabx1dfhxbc9wyyy','system_post_all','authentication.roles.system_post_all.name','authentication.roles.system_post_all.description',1552023386460,1552023386460,0,' create_post',0,1),('nzwf773izfrkirwy47ow3o1xca','system_post_all_public','authentication.roles.system_post_all_public.name','authentication.roles.system_post_all_public.description',1552023386751,1552023386751,0,' create_post_public',0,1),('rhsqatx4yjnk8cwjh785p9tabo','system_admin','authentication.roles.global_admin.name','authentication.roles.global_admin.description',1552023386505,1552023386953,0,' assign_system_admin_role manage_system manage_roles manage_public_channel_properties manage_public_channel_members manage_private_channel_members delete_public_channel create_public_channel manage_private_channel_properties delete_private_channel create_private_channel manage_system_wide_oauth manage_others_webhooks edit_other_users manage_oauth invite_user delete_post delete_others_posts create_team add_user_to_team list_users_without_team manage_jobs create_post_public create_post_ephemeral create_user_access_token read_user_access_token revoke_user_access_token remove_others_reactions list_team_channels join_public_channels read_public_channel view_team read_channel add_reaction remove_reaction upload_file get_public_link create_post use_slash_commands edit_others_posts remove_user_from_team manage_team import_team manage_team_roles manage_channel_roles manage_slash_commands manage_others_slash_commands manage_webhooks edit_post manage_emojis manage_others_emojis',1,1),('s3uda9wt7p8cinzyyjb418o99h','team_admin','authentication.roles.team_admin.name','authentication.roles.team_admin.description',1552023386281,1552023386281,0,' edit_others_posts remove_user_from_team manage_team import_team manage_team_roles manage_channel_roles manage_others_webhooks manage_slash_commands manage_others_slash_commands manage_webhooks delete_post delete_others_posts',1,1),('uowhz7j9s3gx7r37b1twk87uhy','channel_admin','authentication.roles.channel_admin.name','authentication.roles.channel_admin.description',1552023386649,1552023386649,0,' manage_channel_roles',1,1); -/*!40000 ALTER TABLE `Roles` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Schemes` --- - -DROP TABLE IF EXISTS `Schemes`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Schemes` ( - `Id` varchar(26) NOT NULL, - `Name` varchar(64) DEFAULT NULL, - `DisplayName` varchar(128) DEFAULT NULL, - `Description` text, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `Scope` varchar(32) DEFAULT NULL, - `DefaultTeamAdminRole` varchar(64) DEFAULT NULL, - `DefaultTeamUserRole` varchar(64) DEFAULT NULL, - `DefaultChannelAdminRole` varchar(64) DEFAULT NULL, - `DefaultChannelUserRole` varchar(64) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `Name` (`Name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Schemes` --- - -LOCK TABLES `Schemes` WRITE; -/*!40000 ALTER TABLE `Schemes` DISABLE KEYS */; -/*!40000 ALTER TABLE `Schemes` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Sessions` --- - -DROP TABLE IF EXISTS `Sessions`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Sessions` ( - `Id` varchar(26) NOT NULL, - `Token` varchar(26) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `ExpiresAt` bigint(20) DEFAULT NULL, - `LastActivityAt` bigint(20) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `DeviceId` text, - `Roles` varchar(64) DEFAULT NULL, - `IsOAuth` tinyint(1) DEFAULT NULL, - `Props` text, - `ExpiredNotify` tinyint(1) DEFAULT '0', - PRIMARY KEY (`Id`), - KEY `idx_sessions_user_id` (`UserId`), - KEY `idx_sessions_token` (`Token`), - KEY `idx_sessions_expires_at` (`ExpiresAt`), - KEY `idx_sessions_create_at` (`CreateAt`), - KEY `idx_sessions_last_activity_at` (`LastActivityAt`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Sessions` --- - -LOCK TABLES `Sessions` WRITE; -/*!40000 ALTER TABLE `Sessions` DISABLE KEYS */; -/*!40000 ALTER TABLE `Sessions` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Status` --- - -DROP TABLE IF EXISTS `Status`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Status` ( - `UserId` varchar(26) NOT NULL, - `Status` varchar(32) DEFAULT NULL, - `LastActivityAt` bigint(20) DEFAULT NULL, - `Manual` tinyint(1) DEFAULT '0', - PRIMARY KEY (`UserId`), - KEY `idx_status_user_id` (`UserId`), - KEY `idx_status_status` (`Status`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Status` --- - -LOCK TABLES `Status` WRITE; -/*!40000 ALTER TABLE `Status` DISABLE KEYS */; -/*!40000 ALTER TABLE `Status` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Systems` --- - -DROP TABLE IF EXISTS `Systems`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Systems` ( - `Name` varchar(64) NOT NULL, - `Value` text, - PRIMARY KEY (`Name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Systems` --- - -LOCK TABLES `Systems` WRITE; -/*!40000 ALTER TABLE `Systems` DISABLE KEYS */; -INSERT INTO `Systems` VALUES ('AdvancedPermissionsMigrationComplete','true'),('AsymmetricSigningKey','{\"ecdsa_key\":{\"curve\":\"P-256\",\"x\":85473606765277885426098572272657839969684858397331487822403961213130481697183,\"y\":21768024169009006215752583806332445525165014299802801588411746356748078619048,\"d\":77856411969234342853943455407675564464050187128050756722674285242344366590495}}'),('DiagnosticId','8a6b57ugyigti8aqbmzjqixgoe'),('EmojisPermissionsMigrationComplete','true'),('LastSecurityTime','1552023388297'),('Version','5.0.0'); -/*!40000 ALTER TABLE `Systems` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `TeamMembers` --- - -DROP TABLE IF EXISTS `TeamMembers`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `TeamMembers` ( - `TeamId` varchar(26) NOT NULL, - `UserId` varchar(26) NOT NULL, - `Roles` varchar(64) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `SchemeUser` tinyint(4) DEFAULT NULL, - `SchemeAdmin` tinyint(4) DEFAULT NULL, - PRIMARY KEY (`TeamId`,`UserId`), - KEY `idx_teammembers_team_id` (`TeamId`), - KEY `idx_teammembers_user_id` (`UserId`), - KEY `idx_teammembers_delete_at` (`DeleteAt`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `TeamMembers` --- - -LOCK TABLES `TeamMembers` WRITE; -/*!40000 ALTER TABLE `TeamMembers` DISABLE KEYS */; -/*!40000 ALTER TABLE `TeamMembers` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Teams` --- - -DROP TABLE IF EXISTS `Teams`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Teams` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `DisplayName` varchar(64) DEFAULT NULL, - `Name` varchar(64) DEFAULT NULL, - `Description` varchar(255) DEFAULT NULL, - `Email` varchar(128) DEFAULT NULL, - `Type` varchar(255) DEFAULT NULL, - `CompanyName` varchar(64) DEFAULT NULL, - `AllowedDomains` text, - `InviteId` varchar(32) DEFAULT NULL, - `SchemeId` varchar(255) DEFAULT NULL, - `AllowOpenInvite` tinyint(1) DEFAULT NULL, - `LastTeamIconUpdate` bigint(20) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `Name` (`Name`), - KEY `idx_teams_name` (`Name`), - KEY `idx_teams_invite_id` (`InviteId`), - KEY `idx_teams_update_at` (`UpdateAt`), - KEY `idx_teams_create_at` (`CreateAt`), - KEY `idx_teams_delete_at` (`DeleteAt`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Teams` --- - -LOCK TABLES `Teams` WRITE; -/*!40000 ALTER TABLE `Teams` DISABLE KEYS */; -/*!40000 ALTER TABLE `Teams` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Tokens` --- - -DROP TABLE IF EXISTS `Tokens`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Tokens` ( - `Token` varchar(64) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `Type` varchar(64) DEFAULT NULL, - `Extra` varchar(128) DEFAULT NULL, - PRIMARY KEY (`Token`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Tokens` --- - -LOCK TABLES `Tokens` WRITE; -/*!40000 ALTER TABLE `Tokens` DISABLE KEYS */; -/*!40000 ALTER TABLE `Tokens` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `UserAccessTokens` --- - -DROP TABLE IF EXISTS `UserAccessTokens`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `UserAccessTokens` ( - `Id` varchar(26) NOT NULL, - `Token` varchar(26) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `Description` text, - `IsActive` tinyint(1) DEFAULT '1', - PRIMARY KEY (`Id`), - UNIQUE KEY `Token` (`Token`), - KEY `idx_user_access_tokens_token` (`Token`), - KEY `idx_user_access_tokens_user_id` (`UserId`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `UserAccessTokens` --- - -LOCK TABLES `UserAccessTokens` WRITE; -/*!40000 ALTER TABLE `UserAccessTokens` DISABLE KEYS */; -/*!40000 ALTER TABLE `UserAccessTokens` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `Users` --- - -DROP TABLE IF EXISTS `Users`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Users` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `Username` varchar(64) DEFAULT NULL, - `Password` varchar(128) DEFAULT NULL, - `AuthData` varchar(128) DEFAULT NULL, - `AuthService` varchar(32) DEFAULT NULL, - `Email` varchar(128) DEFAULT NULL, - `EmailVerified` tinyint(1) DEFAULT NULL, - `Nickname` varchar(64) DEFAULT NULL, - `FirstName` varchar(64) DEFAULT NULL, - `LastName` varchar(64) DEFAULT NULL, - `Roles` varchar(256) DEFAULT NULL, - `AllowMarketing` tinyint(1) DEFAULT NULL, - `Props` text, - `NotifyProps` text, - `LastPasswordUpdate` bigint(20) DEFAULT NULL, - `LastPictureUpdate` bigint(20) DEFAULT NULL, - `FailedAttempts` int(11) DEFAULT NULL, - `Locale` varchar(5) DEFAULT NULL, - `MfaActive` tinyint(1) DEFAULT NULL, - `MfaSecret` varchar(128) DEFAULT NULL, - `Position` varchar(128) DEFAULT NULL, - `Timezone` varchar(256) DEFAULT '{"automaticTimezone":"","manualTimezone":"","useAutomaticTimezone":"true"}', - PRIMARY KEY (`Id`), - UNIQUE KEY `Username` (`Username`), - UNIQUE KEY `AuthData` (`AuthData`), - UNIQUE KEY `Email` (`Email`), - KEY `idx_users_email` (`Email`), - KEY `idx_users_update_at` (`UpdateAt`), - KEY `idx_users_create_at` (`CreateAt`), - KEY `idx_users_delete_at` (`DeleteAt`), - FULLTEXT KEY `idx_users_all_txt` (`Username`,`FirstName`,`LastName`,`Nickname`,`Email`), - FULLTEXT KEY `idx_users_all_no_full_name_txt` (`Username`,`Nickname`,`Email`), - FULLTEXT KEY `idx_users_names_txt` (`Username`,`FirstName`,`LastName`,`Nickname`), - FULLTEXT KEY `idx_users_names_no_full_name_txt` (`Username`,`Nickname`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `Users` --- - -LOCK TABLES `Users` WRITE; -/*!40000 ALTER TABLE `Users` DISABLE KEYS */; -/*!40000 ALTER TABLE `Users` ENABLE KEYS */; -UNLOCK TABLES; -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - --- Dump completed on 2019-03-08 11:06:52 diff --git a/server/scripts/mattermost-mysql-6.0.0.sql b/server/scripts/mattermost-mysql-6.0.0.sql deleted file mode 100644 index 28516913755..00000000000 --- a/server/scripts/mattermost-mysql-6.0.0.sql +++ /dev/null @@ -1,1198 +0,0 @@ --- MariaDB dump 10.19 Distrib 10.5.10-MariaDB, for Linux (x86_64) --- --- Host: 127.0.0.1 Database: mattermost_test --- ------------------------------------------------------ --- Server version 5.7.12 -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - --- --- Table structure for table `Audits` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Audits` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `Action` text, - `ExtraInfo` text, - `IpAddress` varchar(64) DEFAULT NULL, - `SessionId` varchar(26) DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `idx_audits_user_id` (`UserId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Bots` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Bots` ( - `UserId` varchar(26) NOT NULL, - `Description` text, - `OwnerId` varchar(190) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `LastIconUpdate` bigint(20) DEFAULT NULL, - PRIMARY KEY (`UserId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ChannelMemberHistory` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `ChannelMemberHistory` ( - `ChannelId` varchar(26) NOT NULL, - `UserId` varchar(26) NOT NULL, - `JoinTime` bigint(20) NOT NULL, - `LeaveTime` bigint(20) DEFAULT NULL, - PRIMARY KEY (`ChannelId`,`UserId`,`JoinTime`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ChannelMembers` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `ChannelMembers` ( - `ChannelId` varchar(26) NOT NULL, - `UserId` varchar(26) NOT NULL, - `Roles` varchar(64) DEFAULT NULL, - `LastViewedAt` bigint(20) DEFAULT NULL, - `MsgCount` bigint(20) DEFAULT NULL, - `MentionCount` bigint(20) DEFAULT NULL, - `NotifyProps` json DEFAULT NULL, - `LastUpdateAt` bigint(20) DEFAULT NULL, - `SchemeUser` tinyint(4) DEFAULT NULL, - `SchemeAdmin` tinyint(4) DEFAULT NULL, - `SchemeGuest` tinyint(4) DEFAULT NULL, - `MentionCountRoot` bigint(20) DEFAULT NULL, - `MsgCountRoot` bigint(20) DEFAULT NULL, - PRIMARY KEY (`ChannelId`,`UserId`), - KEY `idx_channelmembers_user_id_channel_id_last_viewed_at` (`UserId`,`ChannelId`,`LastViewedAt`), - KEY `idx_channelmembers_channel_id_scheme_guest_user_id` (`ChannelId`,`SchemeGuest`,`UserId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Channels` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Channels` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `TeamId` varchar(26) DEFAULT NULL, - `Type` varchar(1) DEFAULT NULL, - `DisplayName` varchar(64) DEFAULT NULL, - `Name` varchar(64) DEFAULT NULL, - `Header` text, - `Purpose` varchar(250) DEFAULT NULL, - `LastPostAt` bigint(20) DEFAULT NULL, - `TotalMsgCount` bigint(20) DEFAULT NULL, - `ExtraUpdateAt` bigint(20) DEFAULT NULL, - `CreatorId` varchar(26) DEFAULT NULL, - `SchemeId` varchar(26) DEFAULT NULL, - `GroupConstrained` tinyint(1) DEFAULT NULL, - `Shared` tinyint(1) DEFAULT NULL, - `TotalMsgCountRoot` bigint(20) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `Name` (`Name`,`TeamId`), - KEY `idx_channels_update_at` (`UpdateAt`), - KEY `idx_channels_create_at` (`CreateAt`), - KEY `idx_channels_delete_at` (`DeleteAt`), - KEY `idx_channels_scheme_id` (`SchemeId`), - KEY `idx_channels_team_id_display_name` (`TeamId`,`DisplayName`), - KEY `idx_channels_team_id_type` (`TeamId`,`Type`), - FULLTEXT KEY `idx_channel_search_txt` (`Name`,`DisplayName`,`Purpose`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ClusterDiscovery` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `ClusterDiscovery` ( - `Id` varchar(26) NOT NULL, - `Type` varchar(64) DEFAULT NULL, - `ClusterName` varchar(64) DEFAULT NULL, - `Hostname` text, - `GossipPort` int(11) DEFAULT NULL, - `Port` int(11) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `LastPingAt` bigint(20) DEFAULT NULL, - PRIMARY KEY (`Id`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `CommandWebhooks` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `CommandWebhooks` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `CommandId` varchar(26) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `ChannelId` varchar(26) DEFAULT NULL, - `RootId` varchar(26) DEFAULT NULL, - `UseCount` int(11) DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `idx_command_webhook_create_at` (`CreateAt`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Commands` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Commands` ( - `Id` varchar(26) NOT NULL, - `Token` varchar(26) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `CreatorId` varchar(26) DEFAULT NULL, - `TeamId` varchar(26) DEFAULT NULL, - `Trigger` varchar(128) DEFAULT NULL, - `Method` varchar(1) DEFAULT NULL, - `Username` varchar(64) DEFAULT NULL, - `IconURL` text, - `AutoComplete` tinyint(1) DEFAULT NULL, - `AutoCompleteDesc` text, - `AutoCompleteHint` text, - `DisplayName` varchar(64) DEFAULT NULL, - `Description` varchar(128) DEFAULT NULL, - `URL` text, - `PluginId` varchar(190) DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `idx_command_team_id` (`TeamId`), - KEY `idx_command_update_at` (`UpdateAt`), - KEY `idx_command_create_at` (`CreateAt`), - KEY `idx_command_delete_at` (`DeleteAt`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Compliances` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Compliances` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `Status` varchar(64) DEFAULT NULL, - `Count` int(11) DEFAULT NULL, - `Desc` text, - `Type` varchar(64) DEFAULT NULL, - `StartAt` bigint(20) DEFAULT NULL, - `EndAt` bigint(20) DEFAULT NULL, - `Keywords` text, - `Emails` text, - PRIMARY KEY (`Id`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Emoji` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Emoji` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `CreatorId` varchar(26) DEFAULT NULL, - `Name` varchar(64) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `Name` (`Name`,`DeleteAt`), - KEY `idx_emoji_update_at` (`UpdateAt`), - KEY `idx_emoji_create_at` (`CreateAt`), - KEY `idx_emoji_delete_at` (`DeleteAt`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `FileInfo` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `FileInfo` ( - `Id` varchar(26) NOT NULL, - `CreatorId` varchar(26) DEFAULT NULL, - `PostId` varchar(26) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `Path` text, - `ThumbnailPath` text, - `PreviewPath` text, - `Name` text, - `Extension` varchar(64) DEFAULT NULL, - `Size` bigint(20) DEFAULT NULL, - `MimeType` text, - `Width` int(11) DEFAULT NULL, - `Height` int(11) DEFAULT NULL, - `HasPreviewImage` tinyint(1) DEFAULT NULL, - `MiniPreview` mediumblob, - `Content` longtext, - `RemoteId` varchar(26) DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `idx_fileinfo_update_at` (`UpdateAt`), - KEY `idx_fileinfo_create_at` (`CreateAt`), - KEY `idx_fileinfo_delete_at` (`DeleteAt`), - KEY `idx_fileinfo_postid_at` (`PostId`), - KEY `idx_fileinfo_extension_at` (`Extension`), - FULLTEXT KEY `idx_fileinfo_name_txt` (`Name`), - FULLTEXT KEY `idx_fileinfo_content_txt` (`Content`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `GroupChannels` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `GroupChannels` ( - `GroupId` varchar(26) NOT NULL, - `AutoAdd` tinyint(1) DEFAULT NULL, - `SchemeAdmin` tinyint(1) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `ChannelId` varchar(26) NOT NULL, - PRIMARY KEY (`GroupId`,`ChannelId`), - KEY `idx_groupchannels_schemeadmin` (`SchemeAdmin`), - KEY `idx_groupchannels_channelid` (`ChannelId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `GroupMembers` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `GroupMembers` ( - `GroupId` varchar(26) NOT NULL, - `UserId` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - PRIMARY KEY (`GroupId`,`UserId`), - KEY `idx_groupmembers_create_at` (`CreateAt`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `GroupTeams` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `GroupTeams` ( - `GroupId` varchar(26) NOT NULL, - `AutoAdd` tinyint(1) DEFAULT NULL, - `SchemeAdmin` tinyint(1) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `TeamId` varchar(26) NOT NULL, - PRIMARY KEY (`GroupId`,`TeamId`), - KEY `idx_groupteams_schemeadmin` (`SchemeAdmin`), - KEY `idx_groupteams_teamid` (`TeamId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `IncomingWebhooks` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `IncomingWebhooks` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `ChannelId` varchar(26) DEFAULT NULL, - `TeamId` varchar(26) DEFAULT NULL, - `DisplayName` varchar(64) DEFAULT NULL, - `Description` text, - `Username` varchar(255) DEFAULT NULL, - `IconURL` text, - `ChannelLocked` tinyint(1) DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `idx_incoming_webhook_user_id` (`UserId`), - KEY `idx_incoming_webhook_team_id` (`TeamId`), - KEY `idx_incoming_webhook_update_at` (`UpdateAt`), - KEY `idx_incoming_webhook_create_at` (`CreateAt`), - KEY `idx_incoming_webhook_delete_at` (`DeleteAt`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Jobs` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Jobs` ( - `Id` varchar(26) NOT NULL, - `Type` varchar(32) DEFAULT NULL, - `Priority` bigint(20) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `StartAt` bigint(20) DEFAULT NULL, - `LastActivityAt` bigint(20) DEFAULT NULL, - `Status` varchar(32) DEFAULT NULL, - `Progress` bigint(20) DEFAULT NULL, - `Data` json DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `idx_jobs_type` (`Type`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Licenses` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Licenses` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `Bytes` text, - PRIMARY KEY (`Id`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `LinkMetadata` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `LinkMetadata` ( - `Hash` bigint(20) NOT NULL, - `URL` text, - `Timestamp` bigint(20) DEFAULT NULL, - `Type` varchar(16) DEFAULT NULL, - `Data` json DEFAULT NULL, - PRIMARY KEY (`Hash`), - KEY `idx_link_metadata_url_timestamp` (`URL`(512),`Timestamp`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `OAuthAccessData` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `OAuthAccessData` ( - `Token` varchar(26) NOT NULL, - `RefreshToken` varchar(26) DEFAULT NULL, - `RedirectUri` text, - `ClientId` varchar(26) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `ExpiresAt` bigint(20) DEFAULT NULL, - `Scope` varchar(128) DEFAULT NULL, - PRIMARY KEY (`Token`), - UNIQUE KEY `ClientId` (`ClientId`,`UserId`), - KEY `idx_oauthaccessdata_user_id` (`UserId`), - KEY `idx_oauthaccessdata_refresh_token` (`RefreshToken`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `OAuthApps` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `OAuthApps` ( - `Id` varchar(26) NOT NULL, - `CreatorId` varchar(26) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `ClientSecret` varchar(128) DEFAULT NULL, - `Name` varchar(64) DEFAULT NULL, - `Description` text, - `CallbackUrls` text, - `Homepage` text, - `IsTrusted` tinyint(1) DEFAULT NULL, - `IconURL` text, - PRIMARY KEY (`Id`), - KEY `idx_oauthapps_creator_id` (`CreatorId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `OAuthAuthData` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `OAuthAuthData` ( - `ClientId` varchar(26) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `Code` varchar(128) NOT NULL, - `ExpiresIn` int(11) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `RedirectUri` text, - `State` text, - `Scope` varchar(128) DEFAULT NULL, - PRIMARY KEY (`Code`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `OutgoingWebhooks` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `OutgoingWebhooks` ( - `Id` varchar(26) NOT NULL, - `Token` varchar(26) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `CreatorId` varchar(26) DEFAULT NULL, - `ChannelId` varchar(26) DEFAULT NULL, - `TeamId` varchar(26) DEFAULT NULL, - `TriggerWords` text, - `CallbackURLs` text, - `DisplayName` varchar(64) DEFAULT NULL, - `ContentType` varchar(128) DEFAULT NULL, - `TriggerWhen` int(11) DEFAULT NULL, - `Username` varchar(64) DEFAULT NULL, - `IconURL` text, - `Description` text, - PRIMARY KEY (`Id`), - KEY `idx_outgoing_webhook_team_id` (`TeamId`), - KEY `idx_outgoing_webhook_update_at` (`UpdateAt`), - KEY `idx_outgoing_webhook_create_at` (`CreateAt`), - KEY `idx_outgoing_webhook_delete_at` (`DeleteAt`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `PluginKeyValueStore` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `PluginKeyValueStore` ( - `PluginId` varchar(190) NOT NULL, - `PKey` varchar(50) NOT NULL, - `PValue` mediumblob, - `ExpireAt` bigint(20) DEFAULT NULL, - PRIMARY KEY (`PluginId`,`PKey`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Posts` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Posts` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `ChannelId` varchar(26) DEFAULT NULL, - `RootId` varchar(26) DEFAULT NULL, - `OriginalId` varchar(26) DEFAULT NULL, - `Message` text, - `Type` varchar(26) DEFAULT NULL, - `Props` json DEFAULT NULL, - `Hashtags` text, - `Filenames` text, - `FileIds` text, - `HasReactions` tinyint(1) DEFAULT NULL, - `EditAt` bigint(20) DEFAULT NULL, - `IsPinned` tinyint(1) DEFAULT NULL, - `RemoteId` varchar(26) DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `idx_posts_update_at` (`UpdateAt`), - KEY `idx_posts_create_at` (`CreateAt`), - KEY `idx_posts_delete_at` (`DeleteAt`), - KEY `idx_posts_user_id` (`UserId`), - KEY `idx_posts_is_pinned` (`IsPinned`), - KEY `idx_posts_channel_id_update_at` (`ChannelId`,`UpdateAt`), - KEY `idx_posts_channel_id_delete_at_create_at` (`ChannelId`,`DeleteAt`,`CreateAt`), - KEY `idx_posts_root_id_delete_at` (`RootId`,`DeleteAt`), - FULLTEXT KEY `idx_posts_message_txt` (`Message`), - FULLTEXT KEY `idx_posts_hashtags_txt` (`Hashtags`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Preferences` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Preferences` ( - `UserId` varchar(26) NOT NULL, - `Category` varchar(32) NOT NULL, - `Name` varchar(32) NOT NULL, - `Value` text, - PRIMARY KEY (`UserId`,`Category`,`Name`), - KEY `idx_preferences_category` (`Category`), - KEY `idx_preferences_name` (`Name`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ProductNoticeViewState` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `ProductNoticeViewState` ( - `UserId` varchar(26) NOT NULL, - `NoticeId` varchar(26) NOT NULL, - `Viewed` int(11) DEFAULT NULL, - `Timestamp` bigint(20) DEFAULT NULL, - PRIMARY KEY (`UserId`,`NoticeId`), - KEY `idx_notice_views_timestamp` (`Timestamp`), - KEY `idx_notice_views_notice_id` (`NoticeId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `PublicChannels` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `PublicChannels` ( - `Id` varchar(26) NOT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `TeamId` varchar(26) DEFAULT NULL, - `DisplayName` varchar(64) DEFAULT NULL, - `Name` varchar(64) DEFAULT NULL, - `Header` text, - `Purpose` varchar(250) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `Name` (`Name`,`TeamId`), - KEY `idx_publicchannels_team_id` (`TeamId`), - KEY `idx_publicchannels_delete_at` (`DeleteAt`), - FULLTEXT KEY `idx_publicchannels_search_txt` (`Name`,`DisplayName`,`Purpose`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Reactions` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Reactions` ( - `UserId` varchar(26) NOT NULL, - `PostId` varchar(26) NOT NULL, - `EmojiName` varchar(64) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `RemoteId` varchar(26) DEFAULT NULL, - PRIMARY KEY (`PostId`,`UserId`,`EmojiName`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `RemoteClusters` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `RemoteClusters` ( - `RemoteId` varchar(26) NOT NULL, - `RemoteTeamId` varchar(26) DEFAULT NULL, - `Name` varchar(64) NOT NULL, - `DisplayName` varchar(64) DEFAULT NULL, - `SiteURL` text, - `CreateAt` bigint(20) DEFAULT NULL, - `LastPingAt` bigint(20) DEFAULT NULL, - `Token` varchar(26) DEFAULT NULL, - `RemoteToken` varchar(26) DEFAULT NULL, - `Topics` text, - `CreatorId` varchar(26) DEFAULT NULL, - PRIMARY KEY (`RemoteId`,`Name`), - UNIQUE KEY `remote_clusters_site_url_unique` (`RemoteTeamId`,`SiteURL`(168)) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `RetentionPolicies` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `RetentionPolicies` ( - `Id` varchar(26) NOT NULL, - `DisplayName` varchar(64) DEFAULT NULL, - `PostDuration` bigint(20) DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `IDX_RetentionPolicies_DisplayName` (`DisplayName`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `RetentionPoliciesChannels` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `RetentionPoliciesChannels` ( - `PolicyId` varchar(26) DEFAULT NULL, - `ChannelId` varchar(26) NOT NULL, - PRIMARY KEY (`ChannelId`), - KEY `IDX_RetentionPoliciesChannels_PolicyId` (`PolicyId`), - CONSTRAINT `FK_RetentionPoliciesChannels_RetentionPolicies` FOREIGN KEY (`PolicyId`) REFERENCES `RetentionPolicies` (`Id`) ON DELETE CASCADE -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `RetentionPoliciesTeams` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `RetentionPoliciesTeams` ( - `PolicyId` varchar(26) DEFAULT NULL, - `TeamId` varchar(26) NOT NULL, - PRIMARY KEY (`TeamId`), - KEY `IDX_RetentionPoliciesTeams_PolicyId` (`PolicyId`), - CONSTRAINT `FK_RetentionPoliciesTeams_RetentionPolicies` FOREIGN KEY (`PolicyId`) REFERENCES `RetentionPolicies` (`Id`) ON DELETE CASCADE -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Roles` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Roles` ( - `Id` varchar(26) NOT NULL, - `Name` varchar(64) DEFAULT NULL, - `DisplayName` varchar(128) DEFAULT NULL, - `Description` text, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `Permissions` longtext, - `SchemeManaged` tinyint(1) DEFAULT NULL, - `BuiltIn` tinyint(1) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `Name` (`Name`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Schemes` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Schemes` ( - `Id` varchar(26) NOT NULL, - `Name` varchar(64) DEFAULT NULL, - `DisplayName` varchar(128) DEFAULT NULL, - `Description` text, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `Scope` varchar(32) DEFAULT NULL, - `DefaultTeamAdminRole` varchar(64) DEFAULT NULL, - `DefaultTeamUserRole` varchar(64) DEFAULT NULL, - `DefaultChannelAdminRole` varchar(64) DEFAULT NULL, - `DefaultChannelUserRole` varchar(64) DEFAULT NULL, - `DefaultTeamGuestRole` varchar(64) DEFAULT NULL, - `DefaultChannelGuestRole` varchar(64) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `Name` (`Name`), - KEY `idx_schemes_channel_guest_role` (`DefaultChannelGuestRole`), - KEY `idx_schemes_channel_user_role` (`DefaultChannelUserRole`), - KEY `idx_schemes_channel_admin_role` (`DefaultChannelAdminRole`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Sessions` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Sessions` ( - `Id` varchar(26) NOT NULL, - `Token` varchar(26) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `ExpiresAt` bigint(20) DEFAULT NULL, - `LastActivityAt` bigint(20) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `DeviceId` text, - `Roles` varchar(64) DEFAULT NULL, - `IsOAuth` tinyint(1) DEFAULT NULL, - `Props` json DEFAULT NULL, - `ExpiredNotify` tinyint(1) DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `idx_sessions_user_id` (`UserId`), - KEY `idx_sessions_token` (`Token`), - KEY `idx_sessions_expires_at` (`ExpiresAt`), - KEY `idx_sessions_create_at` (`CreateAt`), - KEY `idx_sessions_last_activity_at` (`LastActivityAt`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `SharedChannelAttachments` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `SharedChannelAttachments` ( - `Id` varchar(26) NOT NULL, - `FileId` varchar(26) DEFAULT NULL, - `RemoteId` varchar(26) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `LastSyncAt` bigint(20) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `FileId` (`FileId`,`RemoteId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `SharedChannelRemotes` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `SharedChannelRemotes` ( - `Id` varchar(26) NOT NULL, - `ChannelId` varchar(26) NOT NULL, - `CreatorId` varchar(26) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `IsInviteAccepted` tinyint(1) DEFAULT NULL, - `IsInviteConfirmed` tinyint(1) DEFAULT NULL, - `RemoteId` varchar(26) DEFAULT NULL, - `LastPostUpdateAt` bigint(20) DEFAULT NULL, - `LastPostId` varchar(26) DEFAULT NULL, - PRIMARY KEY (`Id`,`ChannelId`), - UNIQUE KEY `ChannelId` (`ChannelId`,`RemoteId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `SharedChannelUsers` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `SharedChannelUsers` ( - `Id` varchar(26) NOT NULL, - `UserId` varchar(26) DEFAULT NULL, - `RemoteId` varchar(26) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `LastSyncAt` bigint(20) DEFAULT NULL, - `ChannelId` varchar(26) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `UserId` (`UserId`,`ChannelId`,`RemoteId`), - KEY `idx_sharedchannelusers_remote_id` (`RemoteId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `SharedChannels` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `SharedChannels` ( - `ChannelId` varchar(26) NOT NULL, - `TeamId` varchar(26) DEFAULT NULL, - `Home` tinyint(1) DEFAULT NULL, - `ReadOnly` tinyint(1) DEFAULT NULL, - `ShareName` varchar(64) DEFAULT NULL, - `ShareDisplayName` varchar(64) DEFAULT NULL, - `SharePurpose` varchar(250) DEFAULT NULL, - `ShareHeader` text, - `CreatorId` varchar(26) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `RemoteId` varchar(26) DEFAULT NULL, - PRIMARY KEY (`ChannelId`), - UNIQUE KEY `ShareName` (`ShareName`,`TeamId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `SidebarCategories` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `SidebarCategories` ( - `Id` varchar(128) NOT NULL, - `UserId` varchar(26) DEFAULT NULL, - `TeamId` varchar(26) DEFAULT NULL, - `SortOrder` bigint(20) DEFAULT NULL, - `Sorting` varchar(64) DEFAULT NULL, - `Type` varchar(64) DEFAULT NULL, - `DisplayName` varchar(64) DEFAULT NULL, - `Muted` tinyint(1) DEFAULT NULL, - `Collapsed` tinyint(1) DEFAULT NULL, - PRIMARY KEY (`Id`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `SidebarChannels` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `SidebarChannels` ( - `ChannelId` varchar(26) NOT NULL, - `UserId` varchar(26) NOT NULL, - `CategoryId` varchar(128) NOT NULL, - `SortOrder` bigint(20) DEFAULT NULL, - PRIMARY KEY (`ChannelId`,`UserId`,`CategoryId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Status` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Status` ( - `UserId` varchar(26) NOT NULL, - `Status` varchar(32) DEFAULT NULL, - `Manual` tinyint(1) DEFAULT NULL, - `LastActivityAt` bigint(20) DEFAULT NULL, - `DNDEndTime` bigint(20) DEFAULT NULL, - `PrevStatus` varchar(32) DEFAULT NULL, - PRIMARY KEY (`UserId`), - KEY `idx_status_status_dndendtime` (`Status`,`DNDEndTime`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Systems` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Systems` ( - `Name` varchar(64) NOT NULL, - `Value` text, - PRIMARY KEY (`Name`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `TeamMembers` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `TeamMembers` ( - `TeamId` varchar(26) NOT NULL, - `UserId` varchar(26) NOT NULL, - `Roles` varchar(64) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `SchemeUser` tinyint(4) DEFAULT NULL, - `SchemeAdmin` tinyint(4) DEFAULT NULL, - `SchemeGuest` tinyint(4) DEFAULT NULL, - PRIMARY KEY (`TeamId`,`UserId`), - KEY `idx_teammembers_user_id` (`UserId`), - KEY `idx_teammembers_delete_at` (`DeleteAt`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Teams` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Teams` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `DisplayName` varchar(64) DEFAULT NULL, - `Name` varchar(64) DEFAULT NULL, - `Description` varchar(255) DEFAULT NULL, - `Email` varchar(128) DEFAULT NULL, - `Type` varchar(255) DEFAULT NULL, - `CompanyName` varchar(64) DEFAULT NULL, - `AllowedDomains` text, - `InviteId` varchar(32) DEFAULT NULL, - `SchemeId` varchar(26) DEFAULT NULL, - `AllowOpenInvite` tinyint(1) DEFAULT NULL, - `LastTeamIconUpdate` bigint(20) DEFAULT NULL, - `GroupConstrained` tinyint(1) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `Name` (`Name`), - KEY `idx_teams_invite_id` (`InviteId`), - KEY `idx_teams_update_at` (`UpdateAt`), - KEY `idx_teams_create_at` (`CreateAt`), - KEY `idx_teams_delete_at` (`DeleteAt`), - KEY `idx_teams_scheme_id` (`SchemeId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `TermsOfService` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `TermsOfService` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `Text` text, - PRIMARY KEY (`Id`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ThreadMemberships` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `ThreadMemberships` ( - `PostId` varchar(26) NOT NULL, - `UserId` varchar(26) NOT NULL, - `Following` tinyint(1) DEFAULT NULL, - `LastViewed` bigint(20) DEFAULT NULL, - `LastUpdated` bigint(20) DEFAULT NULL, - `UnreadMentions` bigint(20) DEFAULT NULL, - PRIMARY KEY (`PostId`,`UserId`), - KEY `idx_thread_memberships_last_update_at` (`LastUpdated`), - KEY `idx_thread_memberships_last_view_at` (`LastViewed`), - KEY `idx_thread_memberships_user_id` (`UserId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Threads` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Threads` ( - `PostId` varchar(26) NOT NULL, - `ReplyCount` bigint(20) DEFAULT NULL, - `LastReplyAt` bigint(20) DEFAULT NULL, - `Participants` json DEFAULT NULL, - `ChannelId` varchar(26) DEFAULT NULL, - PRIMARY KEY (`PostId`), - KEY `idx_threads_channel_id_last_reply_at` (`ChannelId`,`LastReplyAt`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Tokens` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Tokens` ( - `Token` varchar(64) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `Type` varchar(64) DEFAULT NULL, - `Extra` text, - PRIMARY KEY (`Token`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `UploadSessions` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `UploadSessions` ( - `Id` varchar(26) NOT NULL, - `Type` varchar(32) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `ChannelId` varchar(26) DEFAULT NULL, - `Filename` text, - `Path` text, - `FileSize` bigint(20) DEFAULT NULL, - `FileOffset` bigint(20) DEFAULT NULL, - `RemoteId` varchar(26) DEFAULT NULL, - `ReqFileId` varchar(26) DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `idx_uploadsessions_user_id` (`UserId`), - KEY `idx_uploadsessions_create_at` (`CreateAt`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `UserAccessTokens` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `UserAccessTokens` ( - `Id` varchar(26) NOT NULL, - `Token` varchar(26) DEFAULT NULL, - `UserId` varchar(26) DEFAULT NULL, - `Description` text, - `IsActive` tinyint(1) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `Token` (`Token`), - KEY `idx_user_access_tokens_user_id` (`UserId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `UserGroups` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `UserGroups` ( - `Id` varchar(26) NOT NULL, - `Name` varchar(64) DEFAULT NULL, - `DisplayName` varchar(128) DEFAULT NULL, - `Description` text, - `Source` varchar(64) DEFAULT NULL, - `RemoteId` varchar(48) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `AllowReference` tinyint(1) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `Name` (`Name`), - UNIQUE KEY `Source` (`Source`,`RemoteId`), - KEY `idx_usergroups_remote_id` (`RemoteId`), - KEY `idx_usergroups_delete_at` (`DeleteAt`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `UserTermsOfService` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `UserTermsOfService` ( - `UserId` varchar(26) NOT NULL, - `TermsOfServiceId` varchar(26) DEFAULT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - PRIMARY KEY (`UserId`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `Users` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `Users` ( - `Id` varchar(26) NOT NULL, - `CreateAt` bigint(20) DEFAULT NULL, - `UpdateAt` bigint(20) DEFAULT NULL, - `DeleteAt` bigint(20) DEFAULT NULL, - `Username` varchar(64) DEFAULT NULL, - `Password` varchar(128) DEFAULT NULL, - `AuthData` varchar(128) DEFAULT NULL, - `AuthService` varchar(32) DEFAULT NULL, - `Email` varchar(128) DEFAULT NULL, - `EmailVerified` tinyint(1) DEFAULT NULL, - `Nickname` varchar(64) DEFAULT NULL, - `FirstName` varchar(64) DEFAULT NULL, - `LastName` varchar(64) DEFAULT NULL, - `Roles` text, - `AllowMarketing` tinyint(1) DEFAULT NULL, - `Props` json DEFAULT NULL, - `NotifyProps` json DEFAULT NULL, - `LastPasswordUpdate` bigint(20) DEFAULT NULL, - `LastPictureUpdate` bigint(20) DEFAULT NULL, - `FailedAttempts` int(11) DEFAULT NULL, - `Locale` varchar(5) DEFAULT NULL, - `MfaActive` tinyint(1) DEFAULT NULL, - `MfaSecret` varchar(128) DEFAULT NULL, - `Position` varchar(128) DEFAULT NULL, - `Timezone` json DEFAULT NULL, - `RemoteId` varchar(26) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `Username` (`Username`), - UNIQUE KEY `AuthData` (`AuthData`), - UNIQUE KEY `Email` (`Email`), - KEY `idx_users_update_at` (`UpdateAt`), - KEY `idx_users_create_at` (`CreateAt`), - KEY `idx_users_delete_at` (`DeleteAt`), - FULLTEXT KEY `idx_users_all_txt` (`Username`,`FirstName`,`LastName`,`Nickname`,`Email`), - FULLTEXT KEY `idx_users_all_no_full_name_txt` (`Username`,`Nickname`,`Email`), - FULLTEXT KEY `idx_users_names_txt` (`Username`,`FirstName`,`LastName`,`Nickname`), - FULLTEXT KEY `idx_users_names_no_full_name_txt` (`Username`,`Nickname`) -); -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `db_migrations` --- - -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `db_migrations` ( - `Version` bigint(20) NOT NULL, - `Name` varchar(64) NOT NULL, - PRIMARY KEY (`Version`) -); -/*!40101 SET character_set_client = @saved_cs_client */; -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - --- Dump completed on 2021-08-31 11:45:07 diff --git a/server/scripts/mirror-docker-images.json b/server/scripts/mirror-docker-images.json index 12d04d88aee..0ed1f02c199 100644 --- a/server/scripts/mirror-docker-images.json +++ b/server/scripts/mirror-docker-images.json @@ -5,9 +5,6 @@ "13": "postgres:13@sha256:1b154a7bbf474aa1a2e67dc7c976835645fe6c3425320e7ad3f5a926d509e8fc", "14": "postgres:14@sha256:1c418702ab77adc7e84c7e726c2ab4f9cb63b8f997341ffcfab56629bab1429d" }, - "mysql": { - "8.0.32": "mysql/mysql-server:8.0.32@sha256:d6c8301b7834c5b9c2b733b10b7e630f441af7bc917c74dba379f24eeeb6a313" - }, "minio": { "RELEASE.2019-10-11T00-38-09Z-1": "minio/minio:RELEASE.2019-10-11T00-38-09Z@sha256:0d02f16a1662653f9b961211b21ed7de04bf04492f44c2b7594bacbfcc519eb5", "RELEASE.2024-06-22T05-26-45Z": "minio/minio:RELEASE.2024-06-22T05-26-45Z@sha256:dda5e13d3df07fae2c1877701998742bcbe3bbb2b9c24c18ed5b9469cc777761" diff --git a/server/scripts/mysql-migration-test.sh b/server/scripts/mysql-migration-test.sh deleted file mode 100755 index 67b3b099a0d..00000000000 --- a/server/scripts/mysql-migration-test.sh +++ /dev/null @@ -1,59 +0,0 @@ -./scripts/jq-dep-check.sh - -TMPDIR=`mktemp -d 2>/dev/null || mktemp -d -t 'tmpConfigDir'` -DUMPDIR=`mktemp -d 2>/dev/null || mktemp -d -t 'dumpDir'` -SCHEMA_VERSION=$1 - -echo "Creating databases" -docker exec mattermost-mysql mysql -uroot -pmostest -e "CREATE DATABASE migrated; CREATE DATABASE latest; GRANT ALL PRIVILEGES ON migrated.* TO mmuser; GRANT ALL PRIVILEGES ON latest.* TO mmuser" - -echo "Importing mysql dump from version ${SCHEMA_VERSION}" -docker exec -i mattermost-mysql mysql -D migrated -uroot -pmostest < $(pwd)/scripts/mattermost-mysql-$SCHEMA_VERSION.sql - -docker exec -i mattermost-mysql mysql -D migrated -uroot -pmostest -e "INSERT INTO Systems (Name, Value) VALUES ('Version', '$SCHEMA_VERSION')" - -echo "Setting up config for db migration" -cat config/config.json | \ - jq '.SqlSettings.DataSource = "mmuser:mostest@tcp(localhost:3306)/migrated?charset=utf8mb4&readTimeout=30s&writeTimeout=30s"' | \ - jq '.SqlSettings.DriverName = "mysql"' > $TMPDIR/config.json - -echo "Running the migration" -make ARGS="db migrate --config $TMPDIR/config.json" run-cli - -echo "Setting up config for fresh db setup" -cat config/config.json | \ - jq '.SqlSettings.DataSource = "mmuser:mostest@tcp(localhost:3306)/latest?charset=utf8mb4&readTimeout=30s&writeTimeout=30s"' | \ - jq '.SqlSettings.DriverName = "mysql"' > $TMPDIR/config.json - -echo "Setting up fresh db" -make ARGS="db migrate --config $TMPDIR/config.json" run-cli - -if [ "$SCHEMA_VERSION" == "5.0.0" ]; then - for i in "ChannelMembers SchemeGuest" "ChannelMembers MsgCountRoot" "ChannelMembers MentionCountRoot" "Channels TotalMsgCountRoot"; do - a=( $i ); - echo "Ignoring known MySQL mismatch: ${a[0]}.${a[1]}" - docker exec mattermost-mysql mysql -D migrated -uroot -pmostest -e "ALTER TABLE ${a[0]} DROP COLUMN ${a[1]};" - docker exec mattermost-mysql mysql -D latest -uroot -pmostest -e "ALTER TABLE ${a[0]} DROP COLUMN ${a[1]};" - done -fi - -echo "Generating dump" -docker exec mattermost-mysql mysqldump --skip-opt --no-data --compact -u root -pmostest migrated > $DUMPDIR/migrated.sql -docker exec mattermost-mysql mysqldump --skip-opt --no-data --compact -u root -pmostest latest > $DUMPDIR/latest.sql - -echo "Removing databases created for db comparison" -docker exec mattermost-mysql mysql -uroot -pmostest -e "DROP DATABASE migrated; DROP DATABASE latest" - -echo "Generating diff" -git diff --word-diff=color $DUMPDIR/migrated.sql $DUMPDIR/latest.sql > $DUMPDIR/diff.txt -diffErrorCode=$? - -if [ $diffErrorCode -eq 0 ]; then - echo "Both schemas are same" -else - echo "Schema mismatch" - cat $DUMPDIR/diff.txt -fi -rm -rf $TMPDIR $DUMPDIR - -exit $diffErrorCode diff --git a/server/scripts/replica-lag-set.sh b/server/scripts/replica-lag-set.sh deleted file mode 100755 index 4c202a73a50..00000000000 --- a/server/scripts/replica-lag-set.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -stmt="STOP SLAVE SQL_THREAD FOR CHANNEL '';CHANGE MASTER TO MASTER_DELAY = $1;START SLAVE SQL_THREAD FOR CHANNEL '';SHOW SLAVE STATUS\G;" -docker exec mattermost-mysql-read-replica sh -c "export MYSQL_PWD=mostest; mysql -u root -e \"$stmt\"" | grep SQL_Delay \ No newline at end of file diff --git a/server/scripts/replica-mysql-config.sh b/server/scripts/replica-mysql-config.sh deleted file mode 100755 index 5ef09379ff6..00000000000 --- a/server/scripts/replica-mysql-config.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -until docker exec mattermost-mysql sh -c 'mysql -u root -pmostest -e ";"' -do - echo "Waiting for mattermost-mysql database connection..." - sleep 4 -done - -priv_stmt='GRANT REPLICATION SLAVE ON *.* TO "mmuser"@"%" IDENTIFIED BY "mostest"; FLUSH PRIVILEGES;' -docker exec mattermost-mysql sh -c "mysql -u root -pmostest -e '$priv_stmt'" - -until docker compose -f docker-compose.makefile.yml exec mysql-read-replica sh -c 'mysql -u root -pmostest -e ";"' -do - echo "Waiting for mysql-read-replica database connection..." - sleep 4 -done - -docker-ip() { - docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$@" -} - -MS_STATUS=`docker exec mattermost-mysql sh -c 'mysql -u root -pmostest -e "SHOW MASTER STATUS"'` -CURRENT_LOG=`echo $MS_STATUS | awk '{print $6}'` -CURRENT_POS=`echo $MS_STATUS | awk '{print $7}'` - -start_slave_stmt="CHANGE MASTER TO MASTER_HOST='$(docker-ip mattermost-mysql)',MASTER_USER='mmuser',MASTER_PASSWORD='mostest',MASTER_LOG_FILE='$CURRENT_LOG',MASTER_LOG_POS=$CURRENT_POS; START SLAVE;" -start_slave_cmd='mysql -u root -pmostest -e "' -start_slave_cmd+="$start_slave_stmt" -start_slave_cmd+='"' -docker exec mattermost-mysql-read-replica sh -c "$start_slave_cmd" - -docker exec mattermost-mysql-read-replica sh -c "mysql -u root -pmostest -e 'SHOW SLAVE STATUS \G'" diff --git a/server/tests/template.load b/server/tests/template.load deleted file mode 100644 index 1c542093c5e..00000000000 --- a/server/tests/template.load +++ /dev/null @@ -1,45 +0,0 @@ -LOAD DATABASE - FROM mysql://{{ .mysql_user }}:{{ .mysql_password }}@mysql:3306/{{ .source_schema }} - INTO pgsql://{{ .pg_user }}:{{ .pg_password }}@postgres:5432/{{ .target_schema }} - -WITH data only, - workers = 8, concurrency = 1, - multiple readers per thread, rows per range = 10000, - prefetch rows = 10000, batch rows = 2500, - create no tables, create no indexes, - preserve index names - -SET PostgreSQL PARAMETERS - maintenance_work_mem to '128MB', - work_mem to '12MB' - -SET MySQL PARAMETERS - net_read_timeout = '120', - net_write_timeout = '120' - - CAST column Channels.Type to "channel_type" drop typemod, - column Teams.Type to "team_type" drop typemod, - column UploadSessions.Type to "upload_session_type" drop typemod, - column ChannelBookmarks.Type to "channel_bookmark_type" drop typemod, - column Drafts.Priority to text, - type int when (= precision 11) to integer drop typemod, - type bigint when (= precision 20) to bigint drop typemod, - type text to varchar drop typemod using remove-null-characters, - type tinyint when (<= precision 4) to boolean using tinyint-to-boolean, - type json to jsonb drop typemod using remove-null-characters - -EXCLUDING TABLE NAMES MATCHING ~, ~ - -BEFORE LOAD DO - $$ ALTER SCHEMA public RENAME TO {{ .source_schema }}; $$, - $$ TRUNCATE TABLE {{ .source_schema }}.systems; $$, - $$ DROP INDEX IF EXISTS {{ .source_schema }}.idx_posts_message_txt; $$, - $$ DROP INDEX IF EXISTS {{ .source_schema }}.idx_fileinfo_content_txt; $$ - -AFTER LOAD DO - $$ UPDATE {{ .source_schema }}.db_migrations set name='add_createat_to_teamembers' where version=92; $$, - $$ CREATE INDEX IF NOT EXISTS idx_posts_message_txt ON {{ .source_schema }}.posts USING gin(to_tsvector('english', message)); $$, - $$ CREATE INDEX IF NOT EXISTS idx_fileinfo_content_txt ON {{ .source_schema }}.fileinfo USING gin(to_tsvector('english', content)); $$, - $$ ALTER SCHEMA {{ .source_schema }} RENAME TO public; $$, - $$ SELECT pg_catalog.set_config('search_path', '"$user", public', false); $$, - $$ ALTER USER {{ .pg_user }} SET SEARCH_PATH TO 'public'; $$; diff --git a/server/tests/test-config.json b/server/tests/test-config.json index f194f90f063..e31be182e45 100644 --- a/server/tests/test-config.json +++ b/server/tests/test-config.json @@ -89,8 +89,8 @@ "IosMinVersion": "" }, "SqlSettings": { - "DriverName": "mysql", - "DataSource": "mmuser:mostest@tcp(localhost:3306)/mattermost_test?charset=utf8mb4\u0026readTimeout=30s\u0026writeTimeout=30s\u0026maxAllowedPacket=4194304", + "DriverName": "postgres", + "DataSource": "postgres://mmuser:mostest@localhost:5432/mattermost_test?sslmode=disable\u0026connect_timeout=10", "DataSourceReplicas": [], "DataSourceSearchReplicas": [], "Trace": false, diff --git a/webapp/channels/src/actions/status_actions.test.ts b/webapp/channels/src/actions/status_actions.test.ts index 20d50398b22..1e92076f751 100644 --- a/webapp/channels/src/actions/status_actions.test.ts +++ b/webapp/channels/src/actions/status_actions.test.ts @@ -132,31 +132,4 @@ describe('actions/status_actions', () => { expect(getStatusesByIds).not.toHaveBeenCalled(); }); }); - - describe('loadStatusesForProfilesMap', () => { - test('load statuses for users map', () => { - const state = cloneDeep(initialState); - const testStore = mockStore(state); - testStore.dispatch(Actions.loadStatusesForProfilesMap({ - user_id2: {id: 'user_id2', username: 'user2'} as UserProfile, - user_id3: {id: 'user_id3', username: 'user3'} as UserProfile, - user_id4: {id: 'user_id4', username: 'user4'} as UserProfile, - })); - expect(getStatusesByIds).toHaveBeenCalledWith((expect as GreatExpectations).arrayContainingExactly(['user_id2', 'user_id3', 'user_id4'])); - }); - - test('load statuses for empty users map', () => { - const state = cloneDeep(initialState); - const testStore = mockStore(state); - testStore.dispatch(Actions.loadStatusesForProfilesMap({})); - expect(getStatusesByIds).not.toHaveBeenCalled(); - }); - - test('load statuses for null users map', () => { - const state = cloneDeep(initialState); - const testStore = mockStore(state); - testStore.dispatch(Actions.loadStatusesForProfilesMap(null)); - expect(getStatusesByIds).not.toHaveBeenCalled(); - }); - }); }); diff --git a/webapp/channels/src/actions/status_actions.ts b/webapp/channels/src/actions/status_actions.ts index 834d05d5151..bbe0c29efdf 100644 --- a/webapp/channels/src/actions/status_actions.ts +++ b/webapp/channels/src/actions/status_actions.ts @@ -80,25 +80,6 @@ export function loadStatusesForProfilesList(users: UserProfile[] | null): Action }; } -export function loadStatusesForProfilesMap(users: Record | UserProfile[] | null): ActionFunc { - return (dispatch) => { - if (users == null) { - return {data: false}; - } - - const statusesToLoad = []; - for (const userId in users) { - if (Object.hasOwn(users, userId)) { - statusesToLoad.push(userId); - } - } - - dispatch(loadStatusesByIds(statusesToLoad)); - - return {data: true}; - }; -} - export function loadStatusesByIds(userIds: string[]): ActionFunc { return (dispatch, getState) => { const state = getState(); diff --git a/webapp/channels/src/actions/user_actions.ts b/webapp/channels/src/actions/user_actions.ts index 1af48cf4b66..82973852d5c 100644 --- a/webapp/channels/src/actions/user_actions.ts +++ b/webapp/channels/src/actions/user_actions.ts @@ -26,7 +26,7 @@ import type {ActionResult} from 'mattermost-redux/types/actions'; import {calculateUnreadCount} from 'mattermost-redux/utils/channel_utils'; import {loadCustomEmojisForCustomStatusesByUserIds} from 'actions/emoji_actions'; -import {loadStatusesForProfilesList, loadStatusesForProfilesMap} from 'actions/status_actions'; +import {loadStatusesForProfilesList} from 'actions/status_actions'; import {getDisplayedChannels} from 'selectors/views/channel_sidebar'; import store from 'stores/redux_store'; @@ -153,16 +153,6 @@ export function loadTeamMembersForProfilesList(profiles: UserProfile[], teamId: }; } -export function loadProfilesWithoutTeam(page: number, perPage: number, options?: Record): ActionFuncAsync { - return async (doDispatch) => { - const {data} = await doDispatch(UserActions.getProfilesWithoutTeam(page, perPage, options)); - - doDispatch(loadStatusesForProfilesMap(data!)); - - return {data}; - }; -} - export function loadTeamMembersAndChannelMembersForProfilesList(profiles: UserProfile[], teamId: string, channelId: string): ActionFuncAsync { return async (doDispatch, doGetState) => { const state = doGetState(); diff --git a/webapp/channels/src/components/admin_console/__snapshots__/database_settings.test.tsx.snap b/webapp/channels/src/components/admin_console/__snapshots__/database_settings.test.tsx.snap index 39786163195..a9800880415 100644 --- a/webapp/channels/src/components/admin_console/__snapshots__/database_settings.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/__snapshots__/database_settings.test.tsx.snap @@ -219,13 +219,8 @@ exports[`components/DatabaseSettings should match snapshot 1`] = ` disabled={false} helpText={ } id="minimumHashtagLength" diff --git a/webapp/channels/src/components/admin_console/access_control/__snapshots__/policies.test.tsx.snap b/webapp/channels/src/components/admin_console/access_control/__snapshots__/policies.test.tsx.snap index b944eece25b..95b58bfd30a 100644 --- a/webapp/channels/src/components/admin_console/access_control/__snapshots__/policies.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/access_control/__snapshots__/policies.test.tsx.snap @@ -70,7 +70,6 @@ exports[`components/admin_console/access_control/PolicyList should match snapsho loading={false} nextPage={[Function]} onSearch={[Function]} - page={0} placeholderEmpty={ { wrapper.update(); expect(mockSearchPolicies).not.toHaveBeenCalled(); - expect(wrapper.find('DataGrid').prop('page')).toBe(0); }); test('should get columns correctly', () => { diff --git a/webapp/channels/src/components/admin_console/access_control/policies.tsx b/webapp/channels/src/components/admin_console/access_control/policies.tsx index d9cf981d1e1..11e66faea6a 100644 --- a/webapp/channels/src/components/admin_console/access_control/policies.tsx +++ b/webapp/channels/src/components/admin_console/access_control/policies.tsx @@ -350,7 +350,6 @@ export default function PolicyList(props: Props): JSX.Element { term={search} placeholderEmpty={placeholderEmpty} rowsContainerStyles={rowsContainerStyles} - page={page} nextPage={nextPage} previousPage={previousPage} /> diff --git a/webapp/channels/src/components/admin_console/access_control/policy_details/channel_list/channel_list.tsx b/webapp/channels/src/components/admin_console/access_control/policy_details/channel_list/channel_list.tsx index 955f494c5ea..4742f21450a 100644 --- a/webapp/channels/src/components/admin_console/access_control/policy_details/channel_list/channel_list.tsx +++ b/webapp/channels/src/components/admin_console/access_control/policy_details/channel_list/channel_list.tsx @@ -545,7 +545,6 @@ class ChannelList extends React.PureComponent { columns={columns} rows={rows} loading={this.state.loading} - page={this.state.page} nextPage={this.nextPage} previousPage={this.previousPage} startCount={startCount} diff --git a/webapp/channels/src/components/admin_console/audit_logging/index.tsx b/webapp/channels/src/components/admin_console/audit_logging/index.tsx index cbe44169c0b..fbd235920bc 100644 --- a/webapp/channels/src/components/admin_console/audit_logging/index.tsx +++ b/webapp/channels/src/components/admin_console/audit_logging/index.tsx @@ -3,7 +3,6 @@ import type {ComponentType} from 'react'; import React from 'react'; -import type {IntlShape} from 'react-intl'; import {useIntl} from 'react-intl'; import {removeAuditCertificate, uploadAuditCertificate} from 'actions/admin_actions'; @@ -16,9 +15,6 @@ import RemoveFileSetting from '../remove_file_setting'; type Props = { id?: string; - config: any; - license: any; - intl: IntlShape; value: any; onChange: (id: string, value: string) => void; disabled: boolean; diff --git a/webapp/channels/src/components/admin_console/content_flagging/content_reviewers/team_reviewers_section/team_reviewers_section.tsx b/webapp/channels/src/components/admin_console/content_flagging/content_reviewers/team_reviewers_section/team_reviewers_section.tsx index 2999fb0ec23..ec6075175ee 100644 --- a/webapp/channels/src/components/admin_console/content_flagging/content_reviewers/team_reviewers_section/team_reviewers_section.tsx +++ b/webapp/channels/src/components/admin_console/content_flagging/content_reviewers/team_reviewers_section/team_reviewers_section.tsx @@ -214,7 +214,6 @@ export default function TeamReviewers({teamReviewersSetting, onChange, disabled} searchTerm='' filters={{}} onRemoveCallback={jest.fn()} - onAddCallback={jest.fn()} channelsToRemove={{}} channelsToAdd={{}} channels={testChannels} @@ -67,7 +66,6 @@ describe('components/admin_console/data_retention_settings/channel_list', () => searchTerm='' filters={{}} onRemoveCallback={jest.fn()} - onAddCallback={jest.fn()} channelsToRemove={{}} channelsToAdd={{}} channels={testChannels} diff --git a/webapp/channels/src/components/admin_console/data_retention_settings/channel_list/channel_list.tsx b/webapp/channels/src/components/admin_console/data_retention_settings/channel_list/channel_list.tsx index 0c5b4f6cc7a..574772114c8 100644 --- a/webapp/channels/src/components/admin_console/data_retention_settings/channel_list/channel_list.tsx +++ b/webapp/channels/src/components/admin_console/data_retention_settings/channel_list/channel_list.tsx @@ -29,7 +29,6 @@ type Props = { policyId?: string; onRemoveCallback: (channel: ChannelWithTeamData) => void; - onAddCallback: (channels: ChannelWithTeamData[]) => void; channelsToRemove: Record; channelsToAdd: Record; @@ -347,7 +346,6 @@ export default class ChannelList extends React.PureComponent { columns={columns} rows={rows} loading={this.state.loading} - page={this.state.page} nextPage={this.nextPage} previousPage={this.previousPage} startCount={startCount} diff --git a/webapp/channels/src/components/admin_console/data_retention_settings/custom_policy_form/__snapshots__/custom_policy_form.test.tsx.snap b/webapp/channels/src/components/admin_console/data_retention_settings/custom_policy_form/__snapshots__/custom_policy_form.test.tsx.snap index aad773dfd80..0f67594b184 100644 --- a/webapp/channels/src/components/admin_console/data_retention_settings/custom_policy_form/__snapshots__/custom_policy_form.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/data_retention_settings/custom_policy_form/__snapshots__/custom_policy_form.test.tsx.snap @@ -193,7 +193,6 @@ exports[`components/admin_console/data_retention_settings/custom_policy_form sho expanded={true} > @@ -455,7 +453,6 @@ exports[`components/admin_console/data_retention_settings/custom_policy_form sho expanded={true} > diff --git a/webapp/channels/src/components/admin_console/data_retention_settings/custom_policy_form/custom_policy_form.tsx b/webapp/channels/src/components/admin_console/data_retention_settings/custom_policy_form/custom_policy_form.tsx index f2832dffd1c..9a32a33d2d1 100644 --- a/webapp/channels/src/components/admin_console/data_retention_settings/custom_policy_form/custom_policy_form.tsx +++ b/webapp/channels/src/components/admin_console/data_retention_settings/custom_policy_form/custom_policy_form.tsx @@ -464,7 +464,6 @@ export default class CustomPolicyForm extends React.PureComponent > > { columns={this.getGlobalPolicyColumns()} rows={this.getGlobalPolicyRows()} loading={false} - page={0} nextPage={() => {}} previousPage={() => {}} startCount={1} @@ -573,7 +572,6 @@ class DataRetentionSettings extends React.PureComponent { columns={this.getCustomPolicyColumns()} rows={this.getCustomPolicyRows(startCount, endCount)} loading={this.state.customPoliciesLoading} - page={this.state.page} nextPage={this.nextPage} previousPage={this.previousPage} startCount={startCount} diff --git a/webapp/channels/src/components/admin_console/data_retention_settings/team_list/__snapshots__/team_list.test.tsx.snap b/webapp/channels/src/components/admin_console/data_retention_settings/team_list/__snapshots__/team_list.test.tsx.snap index 987edbd4423..9f7cc7a031a 100644 --- a/webapp/channels/src/components/admin_console/data_retention_settings/team_list/__snapshots__/team_list.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/data_retention_settings/team_list/__snapshots__/team_list.test.tsx.snap @@ -29,7 +29,6 @@ exports[`components/admin_console/data_retention_settings/team_list should match loading={false} nextPage={[Function]} onSearch={[Function]} - page={0} previousPage={[Function]} rows={ Array [ @@ -110,7 +109,6 @@ exports[`components/admin_console/data_retention_settings/team_list should match loading={false} nextPage={[Function]} onSearch={[Function]} - page={0} previousPage={[Function]} rows={ Array [ diff --git a/webapp/channels/src/components/admin_console/data_retention_settings/team_list/team_list.test.tsx b/webapp/channels/src/components/admin_console/data_retention_settings/team_list/team_list.test.tsx index f8fd178310d..2a6d4774c17 100644 --- a/webapp/channels/src/components/admin_console/data_retention_settings/team_list/team_list.test.tsx +++ b/webapp/channels/src/components/admin_console/data_retention_settings/team_list/team_list.test.tsx @@ -27,7 +27,6 @@ describe('components/admin_console/data_retention_settings/team_list', () => { { void; - onAddCallback: (users: Team[]) => void; teamsToRemove: Record; teamsToAdd: Record; @@ -249,7 +248,6 @@ export default class TeamList extends React.PureComponent { columns={columns} rows={rows} loading={this.state.loading} - page={this.state.page} nextPage={this.nextPage} previousPage={this.previousPage} startCount={startCount} diff --git a/webapp/channels/src/components/admin_console/database_settings.tsx b/webapp/channels/src/components/admin_console/database_settings.tsx index d4cb5eef43b..5d1ac1c8ef1 100644 --- a/webapp/channels/src/components/admin_console/database_settings.tsx +++ b/webapp/channels/src/components/admin_console/database_settings.tsx @@ -67,7 +67,7 @@ const messages = defineMessages({ connMaxIdleTimeTitle: {id: 'admin.sql.connMaxIdleTimeTitle', defaultMessage: 'Maximum Connection Idle Time:'}, connMaxIdleTimeDescription: {id: 'admin.sql.connMaxIdleTimeDescription', defaultMessage: 'Maximum idle time for a connection to the database in milliseconds.'}, minimumHashtagLengthTitle: {id: 'admin.service.minimumHashtagLengthTitle', defaultMessage: 'Minimum Hashtag Length:'}, - minimumHashtagLengthDescription: {id: 'admin.service.minimumHashtagLengthDescription', defaultMessage: 'Minimum number of characters in a hashtag. This must be greater than or equal to 2. MySQL databases must be configured to support searching strings shorter than three characters, see documentation.'}, + minimumHashtagLengthDescription: {id: 'admin.service.minimumHashtagLengthDescription', defaultMessage: 'Minimum number of characters in a hashtag. This must be greater than or equal to 2.'}, traceTitle: {id: 'admin.sql.traceTitle', defaultMessage: 'SQL Statement Logging: '}, traceDescription: {id: 'admin.sql.traceDescription', defaultMessage: '(Development Mode) When true, executing SQL statements are written to the log.'}, }); @@ -321,19 +321,7 @@ export default class DatabaseSettings extends OLDAdminSettings { } placeholder={defineMessage({id: 'admin.service.minimumHashtagLengthExample', defaultMessage: 'E.g.: "3"'})} helpText={ - ( - - {msg} - - ), - }} - /> + } value={this.state.minimumHashtagLength} onChange={this.handleChange} diff --git a/webapp/channels/src/components/admin_console/ldap_wizard/ldap_button_setting.tsx b/webapp/channels/src/components/admin_console/ldap_wizard/ldap_button_setting.tsx index ef1088085c4..df3d1748616 100644 --- a/webapp/channels/src/components/admin_console/ldap_wizard/ldap_button_setting.tsx +++ b/webapp/channels/src/components/admin_console/ldap_wizard/ldap_button_setting.tsx @@ -15,7 +15,6 @@ import {descriptorOrStringToString, renderLabel, renderSettingHelpText} from '.. type Props = { setting: LDAPDefinitionSettingButton; saveNeeded: boolean; - onChange(id: string, value: any): void; disabled: boolean; ldapSettingsState: LdapSettings; onFilterTestResults?: (results: TestLdapFiltersResponse) => void; diff --git a/webapp/channels/src/components/admin_console/ldap_wizard/ldap_wizard.tsx b/webapp/channels/src/components/admin_console/ldap_wizard/ldap_wizard.tsx index 21893b2a686..3e3a3716ff9 100644 --- a/webapp/channels/src/components/admin_console/ldap_wizard/ldap_wizard.tsx +++ b/webapp/channels/src/components/admin_console/ldap_wizard/ldap_wizard.tsx @@ -221,7 +221,6 @@ const LDAPWizard = (props: Props) => { return ( - + ); diff --git a/webapp/channels/src/components/admin_console/license_settings/renew_license_card/renew_license_card.tsx b/webapp/channels/src/components/admin_console/license_settings/renew_license_card/renew_license_card.tsx index fe2052fe1d9..d4ce3512693 100644 --- a/webapp/channels/src/components/admin_console/license_settings/renew_license_card/renew_license_card.tsx +++ b/webapp/channels/src/components/admin_console/license_settings/renew_license_card/renew_license_card.tsx @@ -28,7 +28,6 @@ const RenewLicenseCard: React.FC = ({license, totalUsers, const contactSalesBtn = (
diff --git a/webapp/channels/src/components/admin_console/license_settings/starter_edition/starter_right_panel.tsx b/webapp/channels/src/components/admin_console/license_settings/starter_edition/starter_right_panel.tsx index 9e7df702c0c..545ec0e2f39 100644 --- a/webapp/channels/src/components/admin_console/license_settings/starter_edition/starter_right_panel.tsx +++ b/webapp/channels/src/components/admin_console/license_settings/starter_edition/starter_right_panel.tsx @@ -69,7 +69,6 @@ const StarterRightPanel = () => {
diff --git a/webapp/channels/src/components/admin_console/member_list_group/__snapshots__/member_list_group.test.tsx.snap b/webapp/channels/src/components/admin_console/member_list_group/__snapshots__/member_list_group.test.tsx.snap index 1e7d9709696..11b74ed5525 100644 --- a/webapp/channels/src/components/admin_console/member_list_group/__snapshots__/member_list_group.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/member_list_group/__snapshots__/member_list_group.test.tsx.snap @@ -20,7 +20,6 @@ exports[`admin_console/team_channel_settings/group/GroupList should match snapsh loading={true} nextPage={[Function]} onSearch={[MockFunction]} - page={0} placeholderEmpty={ { columns={columns} rows={rows} loading={this.state.loading} - page={this.state.page} nextPage={this.nextPage} previousPage={this.previousPage} startCount={startCount} diff --git a/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_team_scheme_settings/permission_team_scheme_settings.tsx b/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_team_scheme_settings/permission_team_scheme_settings.tsx index 704195d1371..7322650449e 100644 --- a/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_team_scheme_settings/permission_team_scheme_settings.tsx +++ b/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_team_scheme_settings/permission_team_scheme_settings.tsx @@ -588,7 +588,6 @@ export default class PermissionTeamSchemeSettings extends React.PureComponent team.id)} /> } diff --git a/webapp/channels/src/components/admin_console/secure_connections/modals/secure_connection_accept_invite_modal.tsx b/webapp/channels/src/components/admin_console/secure_connections/modals/secure_connection_accept_invite_modal.tsx index 00fb91c12d6..77ee3804f4b 100644 --- a/webapp/channels/src/components/admin_console/secure_connections/modals/secure_connection_accept_invite_modal.tsx +++ b/webapp/channels/src/components/admin_console/secure_connections/modals/secure_connection_accept_invite_modal.tsx @@ -17,8 +17,6 @@ import TeamSelector from '../team_selector'; import {isErrorState, isPendingState, useTeamOptions} from '../utils'; type Props = { - creating?: boolean; - password?: string; onConfirm: (accept: PartialExcept) => Promise; onCancel?: () => void; onExited: () => void; diff --git a/webapp/channels/src/components/admin_console/secure_connections/secure_connection_detail.tsx b/webapp/channels/src/components/admin_console/secure_connections/secure_connection_detail.tsx index e55580d858d..b226a59c65c 100644 --- a/webapp/channels/src/components/admin_console/secure_connections/secure_connection_detail.tsx +++ b/webapp/channels/src/components/admin_console/secure_connections/secure_connection_detail.tsx @@ -53,7 +53,7 @@ type Params = { connection_id: 'create' | RemoteCluster['remote_id']; }; -type Props = Params & { +type Props = { disabled: boolean; } diff --git a/webapp/channels/src/components/admin_console/server_logs/log_list.tsx b/webapp/channels/src/components/admin_console/server_logs/log_list.tsx index 957910e80b3..266943e4795 100644 --- a/webapp/channels/src/components/admin_console/server_logs/log_list.tsx +++ b/webapp/channels/src/components/admin_console/server_logs/log_list.tsx @@ -22,7 +22,6 @@ type Props = { onFiltersChange: (filters: LogFilter) => void; onSearchChange: (term: string) => void; search: string; - filters: LogFilter; }; type State = { @@ -366,7 +365,6 @@ export default class LogList extends React.PureComponent { term={search} placeholderEmpty={placeholderEmpty} rowsContainerStyles={rowsContainerStyles} - page={this.state.page} nextPage={this.nextPage} previousPage={this.previousPage} filterProps={filterProps} diff --git a/webapp/channels/src/components/admin_console/server_logs/logs.tsx b/webapp/channels/src/components/admin_console/server_logs/logs.tsx index 8512f392e31..b1dafa76bfe 100644 --- a/webapp/channels/src/components/admin_console/server_logs/logs.tsx +++ b/webapp/channels/src/components/admin_console/server_logs/logs.tsx @@ -172,12 +172,6 @@ export default class Logs extends React.PureComponent { onSearchChange={this.onSearchChange} search={this.state.search} onFiltersChange={this.onFiltersChange} - filters={{ - dateFrom: this.state.dateFrom, - dateTo: this.state.dateTo, - logLevels: this.state.logLevels, - serverNames: this.state.serverNames, - }} /> ); diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_table.tsx b/webapp/channels/src/components/admin_console/system_properties/user_properties_table.tsx index 4811652c5fb..4de7dea8742 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_table.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_table.tsx @@ -156,7 +156,6 @@ export function UserPropertiesTable({ value={getValue()} label={formatMessage({id: 'admin.system_properties.user_properties.table.property_name.input.name', defaultMessage: 'Attribute Name'})} deleted={toDelete} - borderless={!warning} testid='property-field-input' autoFocus={isCreatePending(row.original) && !supportsOptions(row.original)} setValue={(value: string) => { @@ -351,7 +350,6 @@ type EditCellProps = { footer?: ReactNode; strong?: boolean; maxLength?: number; - borderless?: boolean; }; const EditCell = (props: EditCellProps) => { const [value, setValue] = useState(props.value); diff --git a/webapp/channels/src/components/admin_console/system_roles/__snapshots__/system_roles.test.tsx.snap b/webapp/channels/src/components/admin_console/system_roles/__snapshots__/system_roles.test.tsx.snap index f4225481ea1..5af54c20656 100644 --- a/webapp/channels/src/components/admin_console/system_roles/__snapshots__/system_roles.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/system_roles/__snapshots__/system_roles.test.tsx.snap @@ -63,7 +63,6 @@ exports[`admin_console/system_roles should match snapshot 1`] = ` endCount={1} loading={false} nextPage={[Function]} - page={1} previousPage={[Function]} rows={ Array [ diff --git a/webapp/channels/src/components/admin_console/system_roles/system_role/system_role_users/__snapshots__/system_role_users.test.tsx.snap b/webapp/channels/src/components/admin_console/system_roles/system_role/system_role_users/__snapshots__/system_role_users.test.tsx.snap index e1fbc575915..151465c7096 100644 --- a/webapp/channels/src/components/admin_console/system_roles/system_role/system_role_users/__snapshots__/system_role_users.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/system_roles/system_role/system_role_users/__snapshots__/system_role_users.test.tsx.snap @@ -167,7 +167,6 @@ exports[`admin_console/system_role_users should match snapshot 1`] = ` loading={true} nextPage={[Function]} onSearch={[Function]} - page={0} previousPage={[Function]} rows={ Array [ @@ -535,7 +534,6 @@ exports[`admin_console/system_role_users should match snapshot with readOnly tru loading={true} nextPage={[Function]} onSearch={[Function]} - page={0} previousPage={[Function]} rows={ Array [ diff --git a/webapp/channels/src/components/admin_console/system_roles/system_role/system_role_users/system_role_users.tsx b/webapp/channels/src/components/admin_console/system_roles/system_role/system_role_users/system_role_users.tsx index d51cff78147..8e828ffb879 100644 --- a/webapp/channels/src/components/admin_console/system_roles/system_role/system_role_users/system_role_users.tsx +++ b/webapp/channels/src/components/admin_console/system_roles/system_role/system_role_users/system_role_users.tsx @@ -236,7 +236,7 @@ export default class SystemRoleUsers extends React.PureComponent { }; render() { - const {page, loading} = this.state; + const {loading} = this.state; const {term, role, usersToAdd, usersToRemove, readOnly} = this.props; const {startCount, endCount, total} = this.getPaginationProps(); return ( @@ -272,7 +272,6 @@ export default class SystemRoleUsers extends React.PureComponent { columns={this.getColumns()} nextPage={this.nextPage} previousPage={this.previousPage} - page={page} startCount={startCount} endCount={endCount} loading={loading} diff --git a/webapp/channels/src/components/admin_console/system_roles/system_roles.tsx b/webapp/channels/src/components/admin_console/system_roles/system_roles.tsx index ceedfddafa2..abecce23fed 100644 --- a/webapp/channels/src/components/admin_console/system_roles/system_roles.tsx +++ b/webapp/channels/src/components/admin_console/system_roles/system_roles.tsx @@ -103,7 +103,6 @@ const SystemRoles = ({roles}: Props) => { { void; doRemoveUserFromTeam: (teamId: string) => Promise; doMakeUserTeamAdmin: (teamId: string) => Promise; doMakeUserTeamMember: (teamId: string) => Promise; diff --git a/webapp/channels/src/components/admin_console/system_users/system_users.scss b/webapp/channels/src/components/admin_console/system_users/system_users.scss index 1d91a57a0ad..ee176a9da81 100644 --- a/webapp/channels/src/components/admin_console/system_users/system_users.scss +++ b/webapp/channels/src/components/admin_console/system_users/system_users.scss @@ -80,11 +80,3 @@ table.systemUsersTable { } } } - -.systemUsers__mySqlAlertBanner { - margin-bottom: 20px; - - .systemUsers__mySqlAlertBanner-buttons { - margin-top: 12px; - } -} diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/channel/list/__snapshots__/channel_list.test.tsx.snap b/webapp/channels/src/components/admin_console/team_channel_settings/channel/list/__snapshots__/channel_list.test.tsx.snap index 8f0c4f10f70..d2813cc081a 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/channel/list/__snapshots__/channel_list.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/team_channel_settings/channel/list/__snapshots__/channel_list.test.tsx.snap @@ -140,7 +140,6 @@ exports[`admin_console/team_channel_settings/channel/ChannelList should match sn loading={false} nextPage={[Function]} onSearch={[Function]} - page={0} placeholderEmpty={ `; -exports[`components/admin_console/team_channel_settings/group/UsersToRemove should match snapshot searching with filters 1`] = ` -
- , - "width": 5, - }, - Object { - "field": "role", - "name": , - "width": 2, - }, - Object { - "field": "groups", - "name": , - "width": 3, - }, - ] - } - endCount={2} - filterProps={ - Object { - "keys": Array [ - "role", - ], - "onFilter": [Function], - "options": Object { - "role": Object { - "keys": Array [ - "system_guest", - "team_user", - "team_admin", - "system_admin", - ], - "name": , - "values": Object { - "system_admin": Object { - "name": , - "value": false, - }, - "system_guest": Object { - "name": , - "value": false, - }, - "team_admin": Object { - "name": , - "value": false, - }, - "team_user": Object { - "name": , - "value": false, - }, - }, - }, - }, - } - } - loading={true} - nextPage={[Function]} - onSearch={[Function]} - page={0} - placeholderEmpty={ - - } - previousPage={[Function]} - rows={Array []} - startCount={1} - term="foo" - total={2} - /> -
-`; - exports[`components/admin_console/team_channel_settings/group/UsersToRemove should match snapshot with 2 users 1`] = `
{ - const wrapper = shallow( - , - ); - expect(wrapper).toMatchSnapshot(); - }); - test('should match snapshot loading', () => { const wrapper = shallow( Promise; loadChannelMembersForProfilesList: (profiles: UserProfile[], channelId: string) => Promise; @@ -345,7 +344,6 @@ export default class UsersToRemove extends React.PureComponent { columns={columns} rows={rows} loading={this.state.loading} - page={this.state.page} nextPage={this.nextPage} previousPage={this.previousPage} startCount={startCount} diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/team/list/team_list.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/team/list/team_list.tsx index 69508f3fb86..ae8c4864f85 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/team/list/team_list.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/team/list/team_list.tsx @@ -386,7 +386,6 @@ export default class TeamList extends React.PureComponent { columns={columns} rows={rows} loading={this.state.loading} - page={this.state.page} nextPage={this.nextPage} previousPage={this.previousPage} startCount={startCount} diff --git a/webapp/channels/src/components/admin_console/user_grid/__snapshots__/user_grid.test.tsx.snap b/webapp/channels/src/components/admin_console/user_grid/__snapshots__/user_grid.test.tsx.snap index 8abba30c24c..a9b76d767de 100644 --- a/webapp/channels/src/components/admin_console/user_grid/__snapshots__/user_grid.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/user_grid/__snapshots__/user_grid.test.tsx.snap @@ -45,7 +45,6 @@ exports[`components/admin_console/user_grid/UserGrid should match snapshot with loading={false} nextPage={[Function]} onSearch={[Function]} - page={0} placeholderEmpty={ { columns={columns} rows={rows} loading={this.state.loading || this.props.loading} - page={this.state.page} nextPage={this.nextPage} previousPage={this.previousPage} startCount={startCount} diff --git a/webapp/channels/src/components/advanced_text_editor/advanced_text_editor.tsx b/webapp/channels/src/components/advanced_text_editor/advanced_text_editor.tsx index 6c8f9076833..f9dfbd0685a 100644 --- a/webapp/channels/src/components/advanced_text_editor/advanced_text_editor.tsx +++ b/webapp/channels/src/components/advanced_text_editor/advanced_text_editor.tsx @@ -819,7 +819,6 @@ const AdvancedTextEditor = ({ useChannelMentions={useChannelMentions} rootId={rootId} onWidthChange={handleWidthChange} - isInEditMode={isInEditMode} /> {attachmentPreview} {!isDisabled && (showFormattingBar || showPreview) && ( diff --git a/webapp/channels/src/components/announcement_bar/announcement_bar_controller.tsx b/webapp/channels/src/components/announcement_bar/announcement_bar_controller.tsx index fdc524ccdbc..549cd5a001f 100644 --- a/webapp/channels/src/components/announcement_bar/announcement_bar_controller.tsx +++ b/webapp/channels/src/components/announcement_bar/announcement_bar_controller.tsx @@ -3,7 +3,7 @@ import React from 'react'; -import type {ClientLicense, ClientConfig, WarnMetricStatus} from '@mattermost/types/config'; +import type {ClientLicense, ClientConfig} from '@mattermost/types/config'; import withGetCloudSubscription from 'components/common/hocs/cloud/with_get_cloud_subscription'; @@ -30,7 +30,6 @@ type Props = { latestError?: { error: any; }; - warnMetricsStatus?: Record; actions: { dismissError: (index: number) => void; getCloudSubscription: () => void; @@ -127,7 +126,6 @@ class AnnouncementBarController extends React.PureComponent { config={this.props.config} license={this.props.license} canViewSystemErrors={this.props.canViewSystemErrors} - warnMetricsStatus={this.props.warnMetricsStatus} /> ); diff --git a/webapp/channels/src/components/announcement_bar/configuration_bar/__snapshots__/configuration_bar.test.tsx.snap b/webapp/channels/src/components/announcement_bar/configuration_bar/__snapshots__/configuration_bar.test.tsx.snap index 5fbb5962b3c..e61f6e0fd79 100644 --- a/webapp/channels/src/components/announcement_bar/configuration_bar/__snapshots__/configuration_bar.test.tsx.snap +++ b/webapp/channels/src/components/announcement_bar/configuration_bar/__snapshots__/configuration_bar.test.tsx.snap @@ -22,14 +22,8 @@ exports[`components/ConfigurationBar should match snapshot, expired 1`] = ` } /> -
} @@ -79,14 +73,8 @@ exports[`components/ConfigurationBar should match snapshot, expired, in grace pe } /> - } diff --git a/webapp/channels/src/components/announcement_bar/configuration_bar/configuration_bar.tsx b/webapp/channels/src/components/announcement_bar/configuration_bar/configuration_bar.tsx index 78a16ff7941..f555dc909a6 100644 --- a/webapp/channels/src/components/announcement_bar/configuration_bar/configuration_bar.tsx +++ b/webapp/channels/src/components/announcement_bar/configuration_bar/configuration_bar.tsx @@ -7,7 +7,7 @@ import {FormattedMessage, injectIntl} from 'react-intl'; import type {IntlShape} from 'react-intl'; import {Link} from 'react-router-dom'; -import type {ClientConfig, WarnMetricStatus} from '@mattermost/types/config'; +import type {ClientConfig} from '@mattermost/types/config'; import type {PreferenceType} from '@mattermost/types/preferences'; import type {ActionResult} from 'mattermost-redux/types/actions'; @@ -34,13 +34,8 @@ type Props = { dismissedExpiringTrialLicense?: boolean; dismissedExpiringLicense?: boolean; dismissedExpiredLicense?: boolean; - dismissedNumberOfActiveUsersWarnMetricStatus?: boolean; - dismissedNumberOfActiveUsersWarnMetricStatusAck?: boolean; - dismissedNumberOfPostsWarnMetricStatus?: boolean; - dismissedNumberOfPostsWarnMetricStatusAck?: boolean; siteURL: string; currentUserId: string; - warnMetricsStatus?: Record; actions: { dismissNotice: (notice: string) => void; savePreferences: (userId: string, preferences: PreferenceType[]) => Promise; @@ -67,8 +62,6 @@ const ConfigurationAnnouncementBar = (props: Props) => { props.actions.dismissNotice(AnnouncementBarMessages.TRIAL_LICENSE_EXPIRING); }; - const renewLinkTelemetry = {success: 'renew_license_banner_success', error: 'renew_license_banner_fail'}; - // System administrators if (props.canViewSystemErrors) { if ((isLicensePastGracePeriod(props.license) || isLicenseExpired(props.license)) && !props.dismissedExpiredLicense) { @@ -93,7 +86,6 @@ const ConfigurationAnnouncementBar = (props: Props) => { {message} } @@ -199,7 +191,6 @@ const ConfigurationAnnouncementBar = (props: Props) => { {message} } diff --git a/webapp/channels/src/components/announcement_bar/contact_sales/contact_us.tsx b/webapp/channels/src/components/announcement_bar/contact_sales/contact_us.tsx index bd0620666fb..fe45e50bd78 100644 --- a/webapp/channels/src/components/announcement_bar/contact_sales/contact_us.tsx +++ b/webapp/channels/src/components/announcement_bar/contact_sales/contact_us.tsx @@ -8,7 +8,6 @@ import useOpenSalesLink from 'components/common/hooks/useOpenSalesLink'; export interface Props { buttonTextElement?: JSX.Element; - eventID?: string; customClass?: string; } diff --git a/webapp/channels/src/components/announcement_bar/renewal_link/index.ts b/webapp/channels/src/components/announcement_bar/renewal_link/index.ts index 412f3bc3609..0e3cca86902 100644 --- a/webapp/channels/src/components/announcement_bar/renewal_link/index.ts +++ b/webapp/channels/src/components/announcement_bar/renewal_link/index.ts @@ -1,23 +1,6 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import type {Dispatch} from 'redux'; - -import {openModal} from 'actions/views/modals'; - import RenewalLink from './renewal_link'; -function mapDispatchToProps(dispatch: Dispatch) { - return { - actions: bindActionCreators( - { - openModal, - }, - dispatch, - ), - }; -} - -export default connect(null, mapDispatchToProps)(RenewalLink); +export default RenewalLink; diff --git a/webapp/channels/src/components/announcement_bar/renewal_link/renewal_link.test.tsx b/webapp/channels/src/components/announcement_bar/renewal_link/renewal_link.test.tsx index ee18430cac9..06a2cc6242d 100644 --- a/webapp/channels/src/components/announcement_bar/renewal_link/renewal_link.test.tsx +++ b/webapp/channels/src/components/announcement_bar/renewal_link/renewal_link.test.tsx @@ -58,15 +58,9 @@ describe('components/RenewalLink', () => { jest.clearAllMocks(); }); - const props = { - actions: { - openModal: jest.fn, - }, - }; - test('should show Contact sales button', async () => { const store = mockStore(initialState); - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); // wait for the promise to resolve and component to update await actImmediate(wrapper); diff --git a/webapp/channels/src/components/announcement_bar/renewal_link/renewal_link.tsx b/webapp/channels/src/components/announcement_bar/renewal_link/renewal_link.tsx index 7a27d359ed6..a79e71e2d70 100644 --- a/webapp/channels/src/components/announcement_bar/renewal_link/renewal_link.tsx +++ b/webapp/channels/src/components/announcement_bar/renewal_link/renewal_link.tsx @@ -6,17 +6,10 @@ import {FormattedMessage} from 'react-intl'; import useOpenSalesLink from 'components/common/hooks/useOpenSalesLink'; -import type {ModalData} from 'types/actions'; - import './renew_link.scss'; export interface RenewalLinkProps { - telemetryInfo?: { success: string; error: string }; - actions: { - openModal:

(modalData: ModalData

) => void; - }; isDisabled?: boolean; - customBtnText?: JSX.Element; className?: string; } diff --git a/webapp/channels/src/components/apps_form/apps_form_component.tsx b/webapp/channels/src/components/apps_form/apps_form_component.tsx index bdf31c3b3fe..fdbc4648d77 100644 --- a/webapp/channels/src/components/apps_form/apps_form_component.tsx +++ b/webapp/channels/src/components/apps_form/apps_form_component.tsx @@ -667,7 +667,6 @@ export class AppsForm extends React.PureComponent { <> {header && ( )} diff --git a/webapp/channels/src/components/apps_form/apps_form_header.tsx b/webapp/channels/src/components/apps_form/apps_form_header.tsx index 21e0b59a326..1b56c51f84a 100644 --- a/webapp/channels/src/components/apps_form/apps_form_header.tsx +++ b/webapp/channels/src/components/apps_form/apps_form_header.tsx @@ -6,7 +6,6 @@ import React from 'react'; import Markdown from 'components/markdown'; type Props = { - id?: string; value: string; }; diff --git a/webapp/channels/src/components/audit_table/audit_table.test.tsx b/webapp/channels/src/components/audit_table/audit_table.test.tsx index 0f6ba16b59d..fa075263862 100644 --- a/webapp/channels/src/components/audit_table/audit_table.test.tsx +++ b/webapp/channels/src/components/audit_table/audit_table.test.tsx @@ -1,11 +1,11 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. +import {shallow} from 'enzyme'; import React from 'react'; import AuditTable from 'components/audit_table/audit_table'; -import {shallowWithIntl} from 'tests/helpers/intl-test-helper'; import {TestHelper} from 'utils/test_helper'; describe('components/audit_table/AuditTable', () => { @@ -23,7 +23,7 @@ describe('components/audit_table/AuditTable', () => { }; test('should match snapshot with no audits', () => { - const wrapper = shallowWithIntl( + const wrapper = shallow( , ); @@ -53,7 +53,7 @@ describe('components/audit_table/AuditTable', () => { ]; const props = {...baseProps, audits}; - const wrapper = shallowWithIntl( + const wrapper = shallow( , ); diff --git a/webapp/channels/src/components/audit_table/audit_table.tsx b/webapp/channels/src/components/audit_table/audit_table.tsx index e69cc03bd72..e3504e41915 100644 --- a/webapp/channels/src/components/audit_table/audit_table.tsx +++ b/webapp/channels/src/components/audit_table/audit_table.tsx @@ -2,27 +2,23 @@ // See LICENSE.txt for license information. import React from 'react'; -import {FormattedMessage, injectIntl} from 'react-intl'; -import type {IntlShape} from 'react-intl'; +import {FormattedMessage} from 'react-intl'; import type {Audit} from '@mattermost/types/audits'; -import type {UserProfile} from '@mattermost/types/users'; import FormatAudit from './format_audit'; type Props = { - intl: IntlShape; audits: Audit[]; showUserId?: boolean; showIp?: boolean; showSession?: boolean; - currentUser: UserProfile; actions: { getMissingProfilesByIds: (userIds: string[]) => void; }; }; -export class AuditTable extends React.PureComponent { +export default class AuditTable extends React.PureComponent { componentDidMount() { const ids = this.props.audits.map((audit) => audit.user_id); this.props.actions.getMissingProfilesByIds(ids); @@ -103,5 +99,3 @@ export class AuditTable extends React.PureComponent { ); } } - -export default injectIntl(AuditTable); diff --git a/webapp/channels/src/components/audit_table/index.ts b/webapp/channels/src/components/audit_table/index.ts index 91f82fada52..af0d494c4df 100644 --- a/webapp/channels/src/components/audit_table/index.ts +++ b/webapp/channels/src/components/audit_table/index.ts @@ -6,18 +6,9 @@ import {bindActionCreators} from 'redux'; import type {Dispatch} from 'redux'; import {getMissingProfilesByIds} from 'mattermost-redux/actions/users'; -import {getCurrentUser} from 'mattermost-redux/selectors/entities/users'; - -import type {GlobalState} from 'types/store'; import AuditTable from './audit_table'; -function mapStateToProps(state: GlobalState) { - return { - currentUser: getCurrentUser(state), - }; -} - function mapDispatchToProps(dispatch: Dispatch) { return { actions: bindActionCreators({ @@ -26,4 +17,4 @@ function mapDispatchToProps(dispatch: Dispatch) { }; } -export default connect(mapStateToProps, mapDispatchToProps)(AuditTable); +export default connect(null, mapDispatchToProps)(AuditTable); diff --git a/webapp/channels/src/components/cloud_usage_modal/index.tsx b/webapp/channels/src/components/cloud_usage_modal/index.tsx index 7f01a26b185..9d280977af5 100644 --- a/webapp/channels/src/components/cloud_usage_modal/index.tsx +++ b/webapp/channels/src/components/cloud_usage_modal/index.tsx @@ -28,7 +28,6 @@ export interface Props { ownLimits?: Limits; backdrop?: boolean; backdropClassName?: string; - className?: string; } export default function CloudUsageModal(props: Props) { diff --git a/webapp/channels/src/components/delete_post_modal/delete_post_modal.tsx b/webapp/channels/src/components/delete_post_modal/delete_post_modal.tsx index 32d73518df5..77e4b0ce645 100644 --- a/webapp/channels/src/components/delete_post_modal/delete_post_modal.tsx +++ b/webapp/channels/src/components/delete_post_modal/delete_post_modal.tsx @@ -19,8 +19,6 @@ const urlFormatForDMGMPermalink = '/:teamName/messages/:username/:postid'; const urlFormatForChannelPermalink = '/:teamName/channels/:channelname/:postid'; type Props = { - channelName?: string; - teamName?: string; post: Post; commentCount: number; isRHS: boolean; diff --git a/webapp/channels/src/components/dialog_router/interactive_dialog_adapter.tsx b/webapp/channels/src/components/dialog_router/interactive_dialog_adapter.tsx index 972861fee85..aa08cf957b4 100644 --- a/webapp/channels/src/components/dialog_router/interactive_dialog_adapter.tsx +++ b/webapp/channels/src/components/dialog_router/interactive_dialog_adapter.tsx @@ -21,7 +21,6 @@ import { type ConversionOptions, type ValidationError, } from 'utils/dialog_conversion'; -import type EmojiMap from 'utils/emoji_map'; import type {DoAppCallResult} from 'types/apps'; @@ -46,7 +45,6 @@ interface Props extends WrappedComponentProps { // Enhanced functionality sourceUrl?: string; // Optional URL for form refresh functionality - emojiMap?: EmojiMap; conversionOptions?: Partial; // Required actions diff --git a/webapp/channels/src/components/dnd_custom_time_picker_modal/dnd_custom_time_picker_modal.tsx b/webapp/channels/src/components/dnd_custom_time_picker_modal/dnd_custom_time_picker_modal.tsx index 2b93f5752ed..3b27ce4698b 100644 --- a/webapp/channels/src/components/dnd_custom_time_picker_modal/dnd_custom_time_picker_modal.tsx +++ b/webapp/channels/src/components/dnd_custom_time_picker_modal/dnd_custom_time_picker_modal.tsx @@ -21,7 +21,6 @@ type Props = { onExited: () => void; userId: string; currentDate: Date; - locale: string; timezone?: string; actions: { diff --git a/webapp/channels/src/components/dnd_custom_time_picker_modal/index.ts b/webapp/channels/src/components/dnd_custom_time_picker_modal/index.ts index 1bc80b6ad5c..edeeaf98c07 100644 --- a/webapp/channels/src/components/dnd_custom_time_picker_modal/index.ts +++ b/webapp/channels/src/components/dnd_custom_time_picker_modal/index.ts @@ -10,8 +10,6 @@ import {setStatus} from 'mattermost-redux/actions/users'; import {getCurrentTimezone} from 'mattermost-redux/selectors/entities/timezone'; import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; -import {getCurrentLocale} from 'selectors/i18n'; - import {makeAsyncComponent} from 'components/async_load'; import type {GlobalState} from 'types/store'; @@ -20,12 +18,10 @@ const DndCustomTimePicker = makeAsyncComponent('DndCustomTimePicker', React.lazy function mapStateToProps(state: GlobalState) { const userId = getCurrentUserId(state); - const locale = getCurrentLocale(state); const timezone = getCurrentTimezone(state); return { userId, - locale, timezone, }; } diff --git a/webapp/channels/src/components/dot_menu/dot_menu.tsx b/webapp/channels/src/components/dot_menu/dot_menu.tsx index db37c32233f..5181ac946a4 100644 --- a/webapp/channels/src/components/dot_menu/dot_menu.tsx +++ b/webapp/channels/src/components/dot_menu/dot_menu.tsx @@ -155,7 +155,6 @@ type Props = { canDelete: boolean; userId: string; threadId: UserThread['id']; - isCollapsedThreadsEnabled: boolean; isFollowingThread?: boolean; isMentionedInRootPost?: boolean; threadReplyCount?: number; diff --git a/webapp/channels/src/components/dot_menu/index.ts b/webapp/channels/src/components/dot_menu/index.ts index 285c8a82679..b75be2b38ec 100644 --- a/webapp/channels/src/components/dot_menu/index.ts +++ b/webapp/channels/src/components/dot_menu/index.ts @@ -123,7 +123,6 @@ function makeMapStateToProps() { threadId, isFollowingThread, isMentionedInRootPost, - isCollapsedThreadsEnabled: collapsedThreads, threadReplyCount, isMobileView: getIsMobileView(state), timezone: getCurrentTimezone(state), diff --git a/webapp/channels/src/components/drafts/draft_row.tsx b/webapp/channels/src/components/drafts/draft_row.tsx index e695a508769..b78126de808 100644 --- a/webapp/channels/src/components/drafts/draft_row.tsx +++ b/webapp/channels/src/components/drafts/draft_row.tsx @@ -60,8 +60,6 @@ type Props = { isRemote?: boolean; scrollIntoView?: boolean; containerClassName?: string; - dataTestId?: string; - dataPostId?: string; } const mockLastBlurAt = {current: 0}; diff --git a/webapp/channels/src/components/file_preview_modal/file_preview_modal.tsx b/webapp/channels/src/components/file_preview_modal/file_preview_modal.tsx index 56571563585..f4d398ab63c 100644 --- a/webapp/channels/src/components/file_preview_modal/file_preview_modal.tsx +++ b/webapp/channels/src/components/file_preview_modal/file_preview_modal.tsx @@ -50,11 +50,6 @@ export type Props = { pluginFilePreviewComponents: FilePreviewComponent[]; onExited: () => void; - /** - * The id of the post the files are attached to - */ - postId?: string; - /** * The post the files are attached to * Either postId or post can be passed to FilePreviewModal diff --git a/webapp/channels/src/components/invitation_modal/no_permissions_view.tsx b/webapp/channels/src/components/invitation_modal/no_permissions_view.tsx index 08398a5ff59..bd0d11f047b 100644 --- a/webapp/channels/src/components/invitation_modal/no_permissions_view.tsx +++ b/webapp/channels/src/components/invitation_modal/no_permissions_view.tsx @@ -12,8 +12,6 @@ import './no_permissions_view.scss'; type Props = { footerClass: string; onDone: () => void; - title?: string; - description?: string; } export default function NoPermissionsView(props: Props) { diff --git a/webapp/channels/src/components/learn_more_trial_modal/learn_more_trial_modal.tsx b/webapp/channels/src/components/learn_more_trial_modal/learn_more_trial_modal.tsx index 74e310d6d50..3a952120c6a 100644 --- a/webapp/channels/src/components/learn_more_trial_modal/learn_more_trial_modal.tsx +++ b/webapp/channels/src/components/learn_more_trial_modal/learn_more_trial_modal.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React, {useCallback, useMemo, useState} from 'react'; +import React, {useCallback, useMemo} from 'react'; import {useIntl} from 'react-intl'; import {useSelector, useDispatch} from 'react-redux'; @@ -34,17 +34,12 @@ const LearnMoreTrialModal = ( onExited, }: Props): JSX.Element | null => { const {formatMessage} = useIntl(); - const [embargoed, setEmbargoed] = useState(false); const dispatch = useDispatch(); // Cloud conditions const license = useSelector(getLicense); const isCloud = license?.Cloud === 'true'; - const handleEmbargoError = useCallback(() => { - setEmbargoed(true); - }, []); - // close this modal once start trial btn is clicked and trial has started successfully const dismissAction = useCallback(() => { dispatch(closeModal(ModalIdentifiers.LEARN_MORE_TRIAL_MODAL)); @@ -52,7 +47,6 @@ const LearnMoreTrialModal = ( const startTrialBtn = ( ); @@ -143,7 +137,6 @@ const LearnMoreTrialModal = ( dataSlides={getSlides} id={'learnMoreTrialModalCarousel'} infiniteSlide={false} - disableNextButton={embargoed} btnsStyle={BtnStyle.CHEVRON} actionButton={startTrialBtn} /> diff --git a/webapp/channels/src/components/learn_more_trial_modal/start_trial_btn.tsx b/webapp/channels/src/components/learn_more_trial_modal/start_trial_btn.tsx index fa4f86a4772..851bd9f75bd 100644 --- a/webapp/channels/src/components/learn_more_trial_modal/start_trial_btn.tsx +++ b/webapp/channels/src/components/learn_more_trial_modal/start_trial_btn.tsx @@ -10,7 +10,6 @@ import './start_trial_btn.scss'; export type StartTrialBtnProps = { onClick?: () => void; - handleEmbargoError?: () => void; btnClass?: string; renderAsButton?: boolean; disabled?: boolean; diff --git a/webapp/channels/src/components/mfa/mfa_controller/mfa_controller.tsx b/webapp/channels/src/components/mfa/mfa_controller/mfa_controller.tsx index 68f3330088f..c7728f6b92c 100644 --- a/webapp/channels/src/components/mfa/mfa_controller/mfa_controller.tsx +++ b/webapp/channels/src/components/mfa/mfa_controller/mfa_controller.tsx @@ -35,17 +35,7 @@ type Props = { }; } -type State = { - enforceMultifactorAuthentication: boolean; -} - -export default class MFAController extends React.PureComponent { - public constructor(props: Props & RouteComponentProps) { - super(props); - - this.state = {enforceMultifactorAuthentication: props.enableMultifactorAuthentication}; - } - +export default class MFAController extends React.PureComponent { public componentDidMount(): void { document.body.classList.add('sticky'); document.getElementById('root')!.classList.add('container-fluid'); @@ -65,10 +55,6 @@ export default class MFAController extends React.PureComponent { - this.setState(state); - }; - public render(): JSX.Element { let backButton; if (this.props.mfa && this.props.enforceMultifactorAuthentication) { @@ -114,8 +100,6 @@ export default class MFAController extends React.PureComponent ( )} diff --git a/webapp/channels/src/components/mfa/setup/setup.tsx b/webapp/channels/src/components/mfa/setup/setup.tsx index 827aa82d4ee..d6bef6ac24b 100644 --- a/webapp/channels/src/components/mfa/setup/setup.tsx +++ b/webapp/channels/src/components/mfa/setup/setup.tsx @@ -8,22 +8,7 @@ import type {UserProfile} from '@mattermost/types/users'; import LocalizedPlaceholderInput from 'components/localized_placeholder_input'; -type MFAControllerState = { - enforceMultifactorAuthentication: boolean; -}; - type Props = { - - /* - * Object containing enforceMultifactorAuthentication - */ - state: MFAControllerState; - - /* - * Function that updates parent component with state props - */ - updateParent: (state: MFAControllerState) => void; - currentUser: UserProfile; siteName?: string; enforceMultifactorAuthentication: boolean; diff --git a/webapp/channels/src/components/multiselect/__snapshots__/multiselect.test.tsx.snap b/webapp/channels/src/components/multiselect/__snapshots__/multiselect.test.tsx.snap index e3e9859c6c9..b9946b4d00e 100644 --- a/webapp/channels/src/components/multiselect/__snapshots__/multiselect.test.tsx.snap +++ b/webapp/channels/src/components/multiselect/__snapshots__/multiselect.test.tsx.snap @@ -161,8 +161,7 @@ exports[`components/multiselect/multiselect MultiSelectList should match snapsho }, ] } - page={0} - perPage={5} + perPage={50} query="" />

extends React.PureComponent, options={optionsToDisplay} optionRenderer={this.props.optionRenderer} ariaLabelRenderer={this.props.ariaLabelRenderer} - page={this.state.page} - perPage={this.props.perPage} - onPageChange={this.props.handlePageChange} onAdd={this.onAdd} onSelect={this.onSelect} loading={this.props.loading} @@ -463,9 +460,6 @@ export class MultiSelect extends React.PureComponent, options={optionsToDisplay} optionRenderer={this.props.optionRenderer} ariaLabelRenderer={this.props.ariaLabelRenderer} - page={this.state.page} - perPage={this.props.perPage} - onPageChange={this.props.handlePageChange} onAdd={this.onAdd} onSelect={this.onSelect} loading={this.props.loading} diff --git a/webapp/channels/src/components/multiselect/multiselect_list.test.tsx b/webapp/channels/src/components/multiselect/multiselect_list.test.tsx index ff8e54fe2c7..a9ebf8e3231 100644 --- a/webapp/channels/src/components/multiselect/multiselect_list.test.tsx +++ b/webapp/channels/src/components/multiselect/multiselect_list.test.tsx @@ -31,13 +31,10 @@ describe('components/multiselect/multiselect', () => { ariaLabelRenderer: element as any, loading: false, onAdd: jest.fn(), - onPageChange: jest.fn(), onSelect: jest.fn(), optionRenderer: element, selectedItemRef, options: users, - perPage: 5, - page: 1, }; test('MultiSelectList should have selected item scrollIntoView to align at bottom of list', () => { diff --git a/webapp/channels/src/components/multiselect/multiselect_list.tsx b/webapp/channels/src/components/multiselect/multiselect_list.tsx index 2288703292c..2793da71aa0 100644 --- a/webapp/channels/src/components/multiselect/multiselect_list.tsx +++ b/webapp/channels/src/components/multiselect/multiselect_list.tsx @@ -16,7 +16,6 @@ export type Props = { ariaLabelRenderer: GetOptionValue; loading?: boolean; onAdd: (value: T) => void; - onPageChange?: (newPage: number, currentPage: number) => void; onSelect: (value: T | null) => void; optionRenderer: ( option: T, @@ -27,8 +26,6 @@ export type Props = { query?: string; selectedItemRef?: React.RefObject; options: T[]; - page: number; - perPage: number; customNoOptionsMessage?: React.ReactNode; } diff --git a/webapp/channels/src/components/onboarding_tasklist/onboarding_tasklist_task.tsx b/webapp/channels/src/components/onboarding_tasklist/onboarding_tasklist_task.tsx index 9914f5b03cb..9d45fae0db9 100644 --- a/webapp/channels/src/components/onboarding_tasklist/onboarding_tasklist_task.tsx +++ b/webapp/channels/src/components/onboarding_tasklist/onboarding_tasklist_task.tsx @@ -8,7 +8,6 @@ import {CompletedAnimation} from './onboarding_tasklist_animations'; export interface TaskProps { label: React.ReactElement; - icon?: React.ReactNode; onClick?: () => void; completedStatus: boolean; } diff --git a/webapp/channels/src/components/post/post_options.tsx b/webapp/channels/src/components/post/post_options.tsx index a9619e80977..f4bb2cd6532 100644 --- a/webapp/channels/src/components/post/post_options.tsx +++ b/webapp/channels/src/components/post/post_options.tsx @@ -33,7 +33,6 @@ type Props = { enableEmojiPicker?: boolean; isReadOnly?: boolean; channelIsArchived?: boolean; - channelIsShared?: boolean; handleCommentClick?: (e: React.MouseEvent) => void; handleJumpClick?: (e: React.MouseEvent) => void; handleDropdownOpened?: (e: boolean) => void; diff --git a/webapp/channels/src/components/post_view/post_message_view/index.ts b/webapp/channels/src/components/post_view/post_message_view/index.ts index 4e60503c864..b4bcbe11725 100644 --- a/webapp/channels/src/components/post_view/post_message_view/index.ts +++ b/webapp/channels/src/components/post_view/post_message_view/index.ts @@ -8,8 +8,6 @@ import {getFeatureFlagValue} from 'mattermost-redux/selectors/entities/general'; import {getTheme, getBool} from 'mattermost-redux/selectors/entities/preferences'; import {getCurrentRelativeTeamUrl} from 'mattermost-redux/selectors/entities/teams'; -import {getIsRhsExpanded, getIsRhsOpen} from 'selectors/rhs'; - import type {GlobalState} from 'types/store'; import PostMessageView from './post_message_view'; @@ -17,8 +15,6 @@ import PostMessageView from './post_message_view'; function mapStateToProps(state: GlobalState) { return { enableFormatting: getBool(state, Preferences.CATEGORY_ADVANCED_SETTINGS, 'formatting', true), - isRHSExpanded: getIsRhsExpanded(state), - isRHSOpen: getIsRhsOpen(state), pluginPostTypes: state.plugins.postTypes, theme: getTheme(state), currentRelativeTeamUrl: getCurrentRelativeTeamUrl(state), diff --git a/webapp/channels/src/components/post_view/post_message_view/post_message_view.tsx b/webapp/channels/src/components/post_view/post_message_view/post_message_view.tsx index 2c178e18be0..fd99d948732 100644 --- a/webapp/channels/src/components/post_view/post_message_view/post_message_view.tsx +++ b/webapp/channels/src/components/post_view/post_message_view/post_message_view.tsx @@ -35,8 +35,6 @@ type Props = { options?: TextFormattingOptions; /* Options specific to text formatting */ compactDisplay?: boolean; /* Set to render post body compactly */ isRHS?: boolean; /* Flags if the post_message_view is for the RHS (Reply). */ - isRHSOpen?: boolean; /* Whether or not the RHS is visible */ - isRHSExpanded?: boolean; /* Whether or not the RHS is expanded */ theme: Theme; /* Logged in user's theme */ pluginPostTypes?: { [postType: string]: PostPluginComponent; diff --git a/webapp/channels/src/components/post_view/post_recent_reactions/post_recent_reactions.tsx b/webapp/channels/src/components/post_view/post_recent_reactions/post_recent_reactions.tsx index a9f4f349503..de123a770de 100644 --- a/webapp/channels/src/components/post_view/post_recent_reactions/post_recent_reactions.tsx +++ b/webapp/channels/src/components/post_view/post_recent_reactions/post_recent_reactions.tsx @@ -11,17 +11,12 @@ import {getEmojiName} from 'mattermost-redux/utils/emoji_utils'; import ChannelPermissionGate from 'components/permissions_gates/channel_permission_gate'; import WithTooltip from 'components/with_tooltip'; -import {Locations} from 'utils/constants'; - import EmojiItem from './recent_reactions_emoji_item'; -type LocationTypes = 'CENTER' | 'RHS_ROOT' | 'RHS_COMMENT'; - type Props = { channelId?: string; postId: string; teamId: string; - location?: LocationTypes; locale: string; emojis: Emoji[]; size: number; @@ -31,13 +26,8 @@ type Props = { }; } -type State = { - location: LocationTypes; -} - -export default class PostRecentReactions extends React.PureComponent { +export default class PostRecentReactions extends React.PureComponent { public static defaultProps: Partial = { - location: Locations.CENTER as 'CENTER', size: 3, }; diff --git a/webapp/channels/src/components/preparing_workspace/single_column_layout.tsx b/webapp/channels/src/components/preparing_workspace/single_column_layout.tsx index 6a58c4ff163..cd3d4e8a71b 100644 --- a/webapp/channels/src/components/preparing_workspace/single_column_layout.tsx +++ b/webapp/channels/src/components/preparing_workspace/single_column_layout.tsx @@ -7,11 +7,7 @@ import './single_column_layout.scss'; type Props = { children: React.ReactNode | React.ReactNodeArray; - beforePath?: boolean; - afterPath?: boolean; style?: React.CSSProperties; - lineDistance?: number; - lineLeft?: number; }; export default function SingleColumnLayout(props: Props) { diff --git a/webapp/channels/src/components/properties_card_view/propertyValueRenderer/user_property_renderer/userPropertyRenderer.test.tsx b/webapp/channels/src/components/properties_card_view/propertyValueRenderer/user_property_renderer/userPropertyRenderer.test.tsx index 35351b8d819..8da12502ced 100644 --- a/webapp/channels/src/components/properties_card_view/propertyValueRenderer/user_property_renderer/userPropertyRenderer.test.tsx +++ b/webapp/channels/src/components/properties_card_view/propertyValueRenderer/user_property_renderer/userPropertyRenderer.test.tsx @@ -32,7 +32,6 @@ describe('UserPropertyRenderer', () => { }, profilesInChannel: {}, profilesNotInChannel: {}, - profilesWithoutTeam: new Set(), profilesInTeam: {}, profilesNotInTeam: {}, statuses: {}, diff --git a/webapp/channels/src/components/rhs_header_post/index.ts b/webapp/channels/src/components/rhs_header_post/index.ts index 810979f3766..d5b143960a0 100644 --- a/webapp/channels/src/components/rhs_header_post/index.ts +++ b/webapp/channels/src/components/rhs_header_post/index.ts @@ -13,11 +13,6 @@ import {getCurrentUserId, getCurrentUserMentionKeys} from 'mattermost-redux/sele import { setRhsExpanded, - showMentions, - showSearchResults, - showFlaggedPosts, - showPinnedPosts, - showChannelFiles, closeRightHandSide, toggleRhsExpanded, goBack, @@ -72,11 +67,6 @@ function makeMapStateToProps() { const actions = { setRhsExpanded, - showSearchResults, - showMentions, - showFlaggedPosts, - showPinnedPosts, - showChannelFiles, closeRightHandSide, toggleRhsExpanded, setThreadFollow, diff --git a/webapp/channels/src/components/rhs_header_post/rhs_header_post.tsx b/webapp/channels/src/components/rhs_header_post/rhs_header_post.tsx index ad56ba02aef..207d0838832 100644 --- a/webapp/channels/src/components/rhs_header_post/rhs_header_post.tsx +++ b/webapp/channels/src/components/rhs_header_post/rhs_header_post.tsx @@ -33,10 +33,6 @@ type Props = WrappedComponentProps & { currentTeam?: Team; currentUserId: string; setRhsExpanded: (b: boolean) => void; - showMentions: () => void; - showSearchResults: () => void; - showFlaggedPosts: () => void; - showPinnedPosts: () => void; goBack: () => void; closeRightHandSide: (e?: React.MouseEvent) => void; toggleRhsExpanded: (e: React.MouseEvent) => void; diff --git a/webapp/channels/src/components/root/actions/index.ts b/webapp/channels/src/components/root/actions/index.ts index 43c7c5d897f..a21c8f074bd 100644 --- a/webapp/channels/src/components/root/actions/index.ts +++ b/webapp/channels/src/components/root/actions/index.ts @@ -22,10 +22,10 @@ import {checkIsFirstAdmin, getCurrentUser, isCurrentUserSystemAdmin} from 'matte import {redirectUserToDefaultTeam, emitUserLoggedOutEvent} from 'actions/global_actions'; import {reloadPage} from 'utils/browser_utils'; -import {ActionTypes, StoragePrefixes} from 'utils/constants'; +import {StoragePrefixes} from 'utils/constants'; import {doesCookieContainsMMUserId} from 'utils/utils'; -import type {ActionFuncAsync, ThunkActionFunc} from 'types/store'; +import type {ThunkActionFunc} from 'types/store'; import type {Translations} from 'types/store/i18n'; export type TranslationPluginFunction = (locale: string) => Translations @@ -84,22 +84,6 @@ export function loadConfigAndMe(): ThunkActionFunc { - // piggyback on plugins state to register a custom post renderer - dispatch({ - type: ActionTypes.RECEIVED_PLUGIN_POST_COMPONENT, - data: { - postTypeId: id, - pluginId: id, - type, - component, - }, - }); - return {data: true}; - }; -} - export function redirectToOnboardingOrDefaultTeam(history: History, searchParams?: URLSearchParams): ThunkActionFunc { return async (dispatch, getState) => { const state = getState(); diff --git a/webapp/channels/src/components/root/index.ts b/webapp/channels/src/components/root/index.ts index 8870de38b0d..6f505e91d3b 100644 --- a/webapp/channels/src/components/root/index.ts +++ b/webapp/channels/src/components/root/index.ts @@ -8,8 +8,6 @@ import {withRouter} from 'react-router-dom'; import {bindActionCreators} from 'redux'; import type {Dispatch} from 'redux'; -import {getFirstAdminSetupComplete} from 'mattermost-redux/actions/general'; -import {getProfiles} from 'mattermost-redux/actions/users'; import {isCurrentLicenseCloud} from 'mattermost-redux/selectors/entities/cloud'; import {getConfig} from 'mattermost-redux/selectors/entities/general'; import {getTeam} from 'mattermost-redux/selectors/entities/teams'; @@ -32,7 +30,6 @@ import type {GlobalState} from 'types/store/index'; import { loadConfigAndMe, - registerCustomPostRenderer, handleLoginLogoutSignal, redirectToOnboardingOrDefaultTeam, } from './actions'; @@ -79,11 +76,8 @@ function mapDispatchToProps(dispatch: Dispatch) { return { actions: bindActionCreators({ loadConfigAndMe, - getFirstAdminSetupComplete, - getProfiles, loadRecentlyUsedCustomEmojis, migrateRecentEmojis, - registerCustomPostRenderer, initializeProducts, handleLoginLogoutSignal, redirectToOnboardingOrDefaultTeam, diff --git a/webapp/channels/src/components/root/root.test.tsx b/webapp/channels/src/components/root/root.test.tsx index db734ba53c1..3d0d8103796 100644 --- a/webapp/channels/src/components/root/root.test.tsx +++ b/webapp/channels/src/components/root/root.test.tsx @@ -36,10 +36,7 @@ jest.mock('actions/global_actions', () => ({ })); jest.mock('mattermost-redux/actions/general', () => ({ - getFirstAdminSetupComplete: jest.fn(() => Promise.resolve({ - type: 'FIRST_ADMIN_COMPLETE_SETUP_RECEIVED', - data: true, - })), + ...jest.requireActual('mattermost-redux/actions/general'), setUrl: () => {}, })); @@ -73,11 +70,8 @@ describe('components/Root', () => { isMeRequested: false, }); }), - getFirstAdminSetupComplete: jest.fn(), - getProfiles: jest.fn(), loadRecentlyUsedCustomEmojis: jest.fn(), migrateRecentEmojis: jest.fn(), - registerCustomPostRenderer: jest.fn(), initializeProducts: jest.fn(), ...bindActionCreators({ handleLoginLogoutSignal, diff --git a/webapp/channels/src/components/setting_picture.tsx b/webapp/channels/src/components/setting_picture.tsx index a5c95be6ded..2ad47cde843 100644 --- a/webapp/channels/src/components/setting_picture.tsx +++ b/webapp/channels/src/components/setting_picture.tsx @@ -29,7 +29,6 @@ type Props = { onFileChange?: (e: ChangeEvent) => void; updateSection?: (e: MouseEvent) => void; imageContext?: string; - maxFileSize?: number; helpText?: ReactNode; } diff --git a/webapp/channels/src/components/single_image_view/index.ts b/webapp/channels/src/components/single_image_view/index.ts index 88770fe0a2f..2920215e214 100644 --- a/webapp/channels/src/components/single_image_view/index.ts +++ b/webapp/channels/src/components/single_image_view/index.ts @@ -11,18 +11,15 @@ import {getConfig} from 'mattermost-redux/selectors/entities/general'; import {toggleEmbedVisibility} from 'actions/post_actions'; import {openModal} from 'actions/views/modals'; -import {getIsRhsOpen} from 'selectors/rhs'; import SingleImageView from 'components/single_image_view/single_image_view'; import type {GlobalState} from 'types/store'; function mapStateToProps(state: GlobalState) { - const isRhsOpen = getIsRhsOpen(state); const config = getConfig(state); return { - isRhsOpen, enablePublicLink: config.EnablePublicLink === 'true', }; } diff --git a/webapp/channels/src/components/single_image_view/single_image_view.tsx b/webapp/channels/src/components/single_image_view/single_image_view.tsx index 6c7d34390e9..63396af8c1a 100644 --- a/webapp/channels/src/components/single_image_view/single_image_view.tsx +++ b/webapp/channels/src/components/single_image_view/single_image_view.tsx @@ -25,7 +25,6 @@ const DISPROPORTIONATE_HEIGHT_RATIO = 20; export interface Props extends PropsFromRedux { postId: string; fileInfo: FileInfo; - isRhsOpen: boolean; enablePublicLink: boolean; compactDisplay?: boolean; isEmbedVisible?: boolean; diff --git a/webapp/channels/src/components/start_trial_form_modal/failure_modal.tsx b/webapp/channels/src/components/start_trial_form_modal/failure_modal.tsx index 34bdfb51d5d..6b14dd5d1d9 100644 --- a/webapp/channels/src/components/start_trial_form_modal/failure_modal.tsx +++ b/webapp/channels/src/components/start_trial_form_modal/failure_modal.tsx @@ -15,7 +15,6 @@ import {ModalIdentifiers} from 'utils/constants'; type Props = { onTryAgain?: () => void; title?: JSX.Element; - subtitle?: JSX.Element; buttonText?: JSX.Element; } diff --git a/webapp/channels/src/components/start_trial_form_modal/index.tsx b/webapp/channels/src/components/start_trial_form_modal/index.tsx index 2163d51c08d..f2cc40e01d5 100644 --- a/webapp/channels/src/components/start_trial_form_modal/index.tsx +++ b/webapp/channels/src/components/start_trial_form_modal/index.tsx @@ -24,7 +24,7 @@ import CountrySelector from 'components/payment_form/country_selector'; import Input, {SIZE} from 'components/widgets/inputs/input/input'; import type {CustomMessageInputType} from 'components/widgets/inputs/input/input'; -import {AboutLinks, LicenseLinks, ModalIdentifiers} from 'utils/constants'; +import {AboutLinks, ModalIdentifiers} from 'utils/constants'; import type {GlobalState} from 'types/store'; @@ -159,28 +159,11 @@ function StartTrialFormModal(props: Props): JSX.Element | null { if (error) { setLoadStatus(TrialLoadStatus.Failed); let title; - let subtitle; let buttonText; let onTryAgain = handleErrorModalTryAgain; if ((data as any).status === 422) { title = (<>); - subtitle = ( - ( - - {text} - - ), - }} - /> - ); buttonText = ( { const defaultProps: Props = { - currentSchemeId: 'xxx', alreadySelected: ['id1'], intl: {} as IntlShape, searchTerm: '', diff --git a/webapp/channels/src/components/team_selector_modal/team_selector_modal.tsx b/webapp/channels/src/components/team_selector_modal/team_selector_modal.tsx index abfabdbe36a..5c728b7ac3d 100644 --- a/webapp/channels/src/components/team_selector_modal/team_selector_modal.tsx +++ b/webapp/channels/src/components/team_selector_modal/team_selector_modal.tsx @@ -23,7 +23,6 @@ const TEAMS_PER_PAGE = 50; type TeamValue = (Team & Value); export type Props = { - currentSchemeId?: string; alreadySelected?: string[]; intl: IntlShape; excludeGroupConstrained?: boolean; @@ -37,7 +36,6 @@ export type Props = { setModalSearchTerm: (searchTerm: string) => void; searchTeams: (searchTerm: string) => void; }; - data?: any; excludePolicyConstrained?: boolean; }; @@ -53,7 +51,6 @@ type State = { export class TeamSelectorModal extends React.PureComponent { private searchTimeoutId?: number; private selectedItemRef?: React.RefObject | undefined; - private currentSchemeId?: string; constructor(props: Props) { super(props); @@ -253,7 +250,6 @@ export class TeamSelectorModal extends React.PureComponent { let teams = [] as Team[]; if (this.props.teams) { teams = this.props.teams.filter((team) => team.delete_at === 0); - teams = teams.filter((team) => team.scheme_id !== this.currentSchemeId); teams = this.props.excludeGroupConstrained ? teams.filter((team) => !team.group_constrained) : teams; if (this.props.alreadySelected) { teams = teams.filter((team) => this.props.alreadySelected?.indexOf(team.id) === -1); diff --git a/webapp/channels/src/components/textbox/textbox.tsx b/webapp/channels/src/components/textbox/textbox.tsx index 35557dfa62b..6bf8ad946ee 100644 --- a/webapp/channels/src/components/textbox/textbox.tsx +++ b/webapp/channels/src/components/textbox/textbox.tsx @@ -71,7 +71,6 @@ export type Props = { priorityProfiles?: UserProfile[]; hasLabels?: boolean; hasError?: boolean; - isInEditMode?: boolean; }; const VISIBLE = {visibility: 'visible'}; diff --git a/webapp/channels/src/components/threading/virtualized_thread_viewer/reply/reply.tsx b/webapp/channels/src/components/threading/virtualized_thread_viewer/reply/reply.tsx index 505e2ca7ed8..4789e1ce6b4 100644 --- a/webapp/channels/src/components/threading/virtualized_thread_viewer/reply/reply.tsx +++ b/webapp/channels/src/components/threading/virtualized_thread_viewer/reply/reply.tsx @@ -12,13 +12,11 @@ import {Locations} from 'utils/constants'; type Props = { a11yIndex: number; - currentUserId: string; isLastPost: boolean; onCardClick: (post: Post) => void; post: Post; previousPostId: string; timestampProps?: Partial; - id?: Post['id']; } function Reply({ diff --git a/webapp/channels/src/components/threading/virtualized_thread_viewer/thread_viewer_row.tsx b/webapp/channels/src/components/threading/virtualized_thread_viewer/thread_viewer_row.tsx index 201332781fb..62f289bd36f 100644 --- a/webapp/channels/src/components/threading/virtualized_thread_viewer/thread_viewer_row.tsx +++ b/webapp/channels/src/components/threading/virtualized_thread_viewer/thread_viewer_row.tsx @@ -22,7 +22,6 @@ import Reply from './reply'; type Props = { a11yIndex: number; - currentUserId: string; isRootPost: boolean; isDeletedPost: boolean; isLastPost: boolean; @@ -37,7 +36,6 @@ type Props = { function noop() {} function ThreadViewerRow({ a11yIndex, - currentUserId, isRootPost, isDeletedPost, isLastPost, @@ -97,7 +95,6 @@ function ThreadViewerRow({ return ( { > void; } diff --git a/webapp/channels/src/components/user_list.tsx b/webapp/channels/src/components/user_list.tsx index e9a1216d43c..f2bf33f6537 100644 --- a/webapp/channels/src/components/user_list.tsx +++ b/webapp/channels/src/components/user_list.tsx @@ -14,7 +14,6 @@ import UserListRow from './user_list_row'; type Props = { rowComponentType?: React.ComponentType; - length?: number; actions?: Array>; actionUserProps?: { [userId: string]: { diff --git a/webapp/channels/src/components/user_settings/advanced/join_leave_section/index.ts b/webapp/channels/src/components/user_settings/advanced/join_leave_section/index.ts index c06dc80cbaf..cdfbdb90bec 100644 --- a/webapp/channels/src/components/user_settings/advanced/join_leave_section/index.ts +++ b/webapp/channels/src/components/user_settings/advanced/join_leave_section/index.ts @@ -5,6 +5,8 @@ import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; import type {Dispatch} from 'redux'; +import type {PreferencesType} from '@mattermost/types/preferences'; + import {savePreferences} from 'mattermost-redux/actions/preferences'; import {Preferences} from 'mattermost-redux/constants'; import {getConfig} from 'mattermost-redux/selectors/entities/general'; @@ -13,9 +15,14 @@ import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; import type {GlobalState} from 'types/store'; -import type {OwnProps} from './join_leave_section'; import JoinLeaveSection from './join_leave_section'; +export type OwnProps = { + adminMode?: boolean; + userId: string; + userPreferences?: PreferencesType; +} + export function mapStateToProps(state: GlobalState, props: OwnProps) { const config = getConfig(state); const enableJoinLeaveMessage = config.EnableJoinLeaveMessageByDefault === 'true'; diff --git a/webapp/channels/src/components/user_settings/advanced/join_leave_section/join_leave_section.tsx b/webapp/channels/src/components/user_settings/advanced/join_leave_section/join_leave_section.tsx index a3c374fe5eb..d601edb5bb8 100644 --- a/webapp/channels/src/components/user_settings/advanced/join_leave_section/join_leave_section.tsx +++ b/webapp/channels/src/components/user_settings/advanced/join_leave_section/join_leave_section.tsx @@ -5,7 +5,7 @@ import React from 'react'; import type {ReactNode, RefObject} from 'react'; import {FormattedMessage} from 'react-intl'; -import type {PreferencesType, PreferenceType} from '@mattermost/types/preferences'; +import type {PreferenceType} from '@mattermost/types/preferences'; import {Preferences} from 'mattermost-redux/constants'; @@ -16,11 +16,7 @@ import type SettingItemMinComponent from 'components/setting_item_min'; import {AdvancedSections} from 'utils/constants'; import {a11yFocus} from 'utils/utils'; -export type OwnProps = { - adminMode?: boolean; - userId: string; - userPreferences?: PreferencesType; -} +import type {OwnProps} from './index'; type Props = OwnProps & { active: boolean; diff --git a/webapp/channels/src/components/user_settings/advanced/performance_debugging_section/index.ts b/webapp/channels/src/components/user_settings/advanced/performance_debugging_section/index.ts index 742f421fd7d..2f0c8d27e15 100644 --- a/webapp/channels/src/components/user_settings/advanced/performance_debugging_section/index.ts +++ b/webapp/channels/src/components/user_settings/advanced/performance_debugging_section/index.ts @@ -12,9 +12,13 @@ import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; import type {GlobalState} from 'types/store'; -import type {OwnProps} from './performance_debugging_section'; import PerformanceDebuggingSection from './performance_debugging_section'; +export type OwnProps = { + adminMode?: boolean; + userId: string; +} + function mapStateToProps(state: GlobalState, props: OwnProps) { const userPreferences = props.adminMode && props.userId ? getUserPreferences(state, props.userId) : undefined; diff --git a/webapp/channels/src/components/user_settings/advanced/performance_debugging_section/performance_debugging_section.tsx b/webapp/channels/src/components/user_settings/advanced/performance_debugging_section/performance_debugging_section.tsx index 15c293329a8..545e0dbb996 100644 --- a/webapp/channels/src/components/user_settings/advanced/performance_debugging_section/performance_debugging_section.tsx +++ b/webapp/channels/src/components/user_settings/advanced/performance_debugging_section/performance_debugging_section.tsx @@ -14,12 +14,7 @@ import {AdvancedSections} from 'utils/constants'; import type {PropsFromRedux} from './index'; -export type OwnProps = { - adminMode?: boolean; - userId: string; -} - -type Props = PropsFromRedux & OwnProps & { +type Props = PropsFromRedux & { active: boolean; areAllSectionsInactive: boolean; onUpdateSection: (section?: string) => void; diff --git a/webapp/channels/src/components/user_settings/display/__snapshots__/user_settings_display.test.tsx.snap b/webapp/channels/src/components/user_settings/display/__snapshots__/user_settings_display.test.tsx.snap index 034a6b9d35e..ce194fd020e 100644 --- a/webapp/channels/src/components/user_settings/display/__snapshots__/user_settings_display.test.tsx.snap +++ b/webapp/channels/src/components/user_settings/display/__snapshots__/user_settings_display.test.tsx.snap @@ -323,7 +323,6 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps } max={ void; - adminMode?: boolean; - userPreferences?: PreferencesType; } type Props = OwnProps & { diff --git a/webapp/channels/src/components/user_settings/display/user_settings_display.tsx b/webapp/channels/src/components/user_settings/display/user_settings_display.tsx index 64ac5a472a1..5b1b0d0fd27 100644 --- a/webapp/channels/src/components/user_settings/display/user_settings_display.tsx +++ b/webapp/channels/src/components/user_settings/display/user_settings_display.tsx @@ -1165,8 +1165,6 @@ export default class UserSettingsDisplay extends React.PureComponent )} /> diff --git a/webapp/channels/src/components/user_settings/general/user_settings_general.tsx b/webapp/channels/src/components/user_settings/general/user_settings_general.tsx index 58ac52d4170..b23ddb90a57 100644 --- a/webapp/channels/src/components/user_settings/general/user_settings_general.tsx +++ b/webapp/channels/src/components/user_settings/general/user_settings_general.tsx @@ -1697,7 +1697,6 @@ export class UserSettingsGeneralTab extends PureComponent { onFileChange={this.updatePicture} submitActive={this.submitActive} loadingPicture={this.state.loadingPicture} - maxFileSize={this.props.maxFileSize} helpText={helpText} /> ); diff --git a/webapp/channels/src/components/user_settings/notifications/index.ts b/webapp/channels/src/components/user_settings/notifications/index.ts index 480f77673e9..fb1abd8d9e8 100644 --- a/webapp/channels/src/components/user_settings/notifications/index.ts +++ b/webapp/channels/src/components/user_settings/notifications/index.ts @@ -3,6 +3,9 @@ import {connect, type ConnectedProps} from 'react-redux'; +import type {PreferencesType} from '@mattermost/types/preferences'; +import type {UserProfile} from '@mattermost/types/users'; + import {patchUser, updateMe} from 'mattermost-redux/actions/users'; import {getSubscriptionProduct} from 'mattermost-redux/selectors/entities/cloud'; import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general'; @@ -17,9 +20,18 @@ import {isEnterpriseOrCloudOrSKUStarterFree} from 'utils/license_utils'; import type {GlobalState} from 'types/store'; -import type {OwnProps} from './user_settings_notifications'; import UserSettingsNotifications from './user_settings_notifications'; +export type OwnProps = { + user: UserProfile; + updateSection: (section: string) => void; + activeSection: string; + closeModal: () => void; + collapseModal: () => void; + adminMode?: boolean; + userPreferences?: PreferencesType; +} + const mapStateToProps = (state: GlobalState, props: OwnProps) => { // server config, related to server configuration, not the user const config = getConfig(state); diff --git a/webapp/channels/src/components/user_settings/notifications/user_settings_notifications.tsx b/webapp/channels/src/components/user_settings/notifications/user_settings_notifications.tsx index c5589d227a7..3d667e695d9 100644 --- a/webapp/channels/src/components/user_settings/notifications/user_settings_notifications.tsx +++ b/webapp/channels/src/components/user_settings/notifications/user_settings_notifications.tsx @@ -12,7 +12,6 @@ import {components} from 'react-select'; import CreatableReactSelect from 'react-select/creatable'; import {LightbulbOutlineIcon} from '@mattermost/compass-icons/components'; -import type {PreferencesType} from '@mattermost/types/preferences'; import type {UserNotifyProps, UserProfile} from '@mattermost/types/users'; import ExternalLink from 'components/external_link'; @@ -33,7 +32,7 @@ import SendTestNotificationNotice from './send_test_notification_notice'; import SettingDesktopHeader from '../headers/setting_desktop_header'; import SettingMobileHeader from '../headers/setting_mobile_header'; -import type {PropsFromRedux} from './index'; +import type {OwnProps, PropsFromRedux} from './index'; const WHITE_SPACE_REGEX = /\s+/g; const COMMA_REGEX = /,/g; @@ -43,16 +42,6 @@ type MultiInputValue = { value: string; } -export type OwnProps = { - user: UserProfile; - updateSection: (section: string) => void; - activeSection: string; - closeModal: () => void; - collapseModal: () => void; - adminMode?: boolean; - userPreferences?: PreferencesType; -} - export type Props = PropsFromRedux & OwnProps & WrappedComponentProps; type State = { diff --git a/webapp/channels/src/components/user_settings/sidebar/limit_visible_gms_dms/index.ts b/webapp/channels/src/components/user_settings/sidebar/limit_visible_gms_dms/index.ts index a89a997734e..804c1151ecc 100644 --- a/webapp/channels/src/components/user_settings/sidebar/limit_visible_gms_dms/index.ts +++ b/webapp/channels/src/components/user_settings/sidebar/limit_visible_gms_dms/index.ts @@ -3,15 +3,22 @@ import {connect} from 'react-redux'; +import type {PreferencesType} from '@mattermost/types/preferences'; + import {savePreferences} from 'mattermost-redux/actions/preferences'; import {getVisibleDmGmLimit} from 'mattermost-redux/selectors/entities/preferences'; import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; import type {GlobalState} from 'types/store'; -import type {OwnProps} from './limit_visible_gms_dms'; import LimitVisibleGMsDMs from './limit_visible_gms_dms'; +export type OwnProps = { + adminMode?: boolean; + userId: string; + userPreferences?: PreferencesType; +} + function mapStateToProps(state: GlobalState, ownProps: OwnProps) { const userPreferences = ownProps.adminMode && ownProps.userPreferences ? ownProps.userPreferences : undefined; return { diff --git a/webapp/channels/src/components/user_settings/sidebar/limit_visible_gms_dms/limit_visible_gms_dms.tsx b/webapp/channels/src/components/user_settings/sidebar/limit_visible_gms_dms/limit_visible_gms_dms.tsx index 7059c3fc159..815d1b96583 100644 --- a/webapp/channels/src/components/user_settings/sidebar/limit_visible_gms_dms/limit_visible_gms_dms.tsx +++ b/webapp/channels/src/components/user_settings/sidebar/limit_visible_gms_dms/limit_visible_gms_dms.tsx @@ -7,7 +7,7 @@ import {FormattedMessage} from 'react-intl'; import ReactSelect from 'react-select'; import type {OnChangeValue, StylesConfig} from 'react-select'; -import type {PreferencesType, PreferenceType} from '@mattermost/types/preferences'; +import type {PreferenceType} from '@mattermost/types/preferences'; import {Preferences} from 'mattermost-redux/constants'; import type {ActionResult} from 'mattermost-redux/types/actions'; @@ -16,17 +16,13 @@ import SettingItemMax from 'components/setting_item_max'; import SettingItemMin from 'components/setting_item_min'; import type SettingItemMinComponent from 'components/setting_item_min'; +import type {OwnProps} from './index'; + type Limit = { value: number; label: string; }; -export type OwnProps = { - adminMode?: boolean; - userId: string; - userPreferences?: PreferencesType; -} - type Props = OwnProps & { active: boolean; areAllSectionsInactive: boolean; diff --git a/webapp/channels/src/components/user_settings/sidebar/show_unreads_category/index.ts b/webapp/channels/src/components/user_settings/sidebar/show_unreads_category/index.ts index ae54045d337..43d5d7fcc3c 100644 --- a/webapp/channels/src/components/user_settings/sidebar/show_unreads_category/index.ts +++ b/webapp/channels/src/components/user_settings/sidebar/show_unreads_category/index.ts @@ -3,6 +3,8 @@ import {connect} from 'react-redux'; +import type {PreferencesType} from '@mattermost/types/preferences'; + import {savePreferences} from 'mattermost-redux/actions/preferences'; import { shouldShowUnreadsCategory, @@ -11,9 +13,14 @@ import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; import type {GlobalState} from 'types/store'; -import type {OwnProps} from './show_unreads_category'; import ShowUnreadsCategory from './show_unreads_category'; +export type OwnProps = { + adminMode?: boolean; + userId: string; + userPreferences?: PreferencesType; +} + function mapStateToProps(state: GlobalState, props: OwnProps) { const userPreferences = props.adminMode && props.userPreferences ? props.userPreferences : undefined; return { diff --git a/webapp/channels/src/components/user_settings/sidebar/show_unreads_category/show_unreads_category.tsx b/webapp/channels/src/components/user_settings/sidebar/show_unreads_category/show_unreads_category.tsx index 48f4b118c0b..faddab3288d 100644 --- a/webapp/channels/src/components/user_settings/sidebar/show_unreads_category/show_unreads_category.tsx +++ b/webapp/channels/src/components/user_settings/sidebar/show_unreads_category/show_unreads_category.tsx @@ -5,7 +5,7 @@ import React from 'react'; import type {RefObject} from 'react'; import {FormattedMessage} from 'react-intl'; -import type {PreferencesType, PreferenceType} from '@mattermost/types/preferences'; +import type {PreferenceType} from '@mattermost/types/preferences'; import {Preferences} from 'mattermost-redux/constants'; import type {ActionResult} from 'mattermost-redux/types/actions'; @@ -16,11 +16,7 @@ import type SettingItemMinComponent from 'components/setting_item_min'; import {a11yFocus} from 'utils/utils'; -export type OwnProps = { - adminMode?: boolean; - userId: string; - userPreferences?: PreferencesType; -} +import type {OwnProps} from './index'; type Props = OwnProps & { active: boolean; diff --git a/webapp/channels/src/components/youtube_video/__snapshots__/youtube_video.test.tsx.snap b/webapp/channels/src/components/youtube_video/__snapshots__/youtube_video.test.tsx.snap index 8bf20d567ef..74e35471882 100644 --- a/webapp/channels/src/components/youtube_video/__snapshots__/youtube_video.test.tsx.snap +++ b/webapp/channels/src/components/youtube_video/__snapshots__/youtube_video.test.tsx.snap @@ -68,7 +68,6 @@ exports[`YoutubeVideo should match init snapshot 1`] = ` onError={[Function]} play={[Function]} thumbnailUrl="https://img.youtube.com/vi/xqCoNej8Zxo/maxresdefault.jpg" - useMaxResThumbnail={true} videoTitle="Youtube title" >
void; thumbnailUrl: string; - useMaxResThumbnail: boolean; }; function YouTubeThumbnail({play, videoTitle, onError, thumbnailUrl}: YouTubeThumbnailProps) { @@ -183,7 +181,6 @@ export default class YoutubeVideo extends React.PureComponent { videoTitle={videoTitle} onError={this.handleImageError} thumbnailUrl={thumbnailUrl} - useMaxResThumbnail={this.state.useMaxResThumbnail} /> ); } diff --git a/webapp/channels/src/i18n/en.json b/webapp/channels/src/i18n/en.json index 63cab25f6a1..c55621e1925 100644 --- a/webapp/channels/src/i18n/en.json +++ b/webapp/channels/src/i18n/en.json @@ -2709,7 +2709,7 @@ "admin.service.maximumPayloadSizeDescription": "The maximum number of bytes allowed in the payload of incoming HTTP calls", "admin.service.mfaDesc": "When true, users with AD/LDAP or email login can add multi-factor authentication to their account using an authenticator app.", "admin.service.mfaTitle": "Enable Multi-factor Authentication:", - "admin.service.minimumHashtagLengthDescription": "Minimum number of characters in a hashtag. This must be greater than or equal to 2. MySQL databases must be configured to support searching strings shorter than three characters, see documentation.", + "admin.service.minimumHashtagLengthDescription": "Minimum number of characters in a hashtag. This must be greater than or equal to 2.", "admin.service.minimumHashtagLengthExample": "E.g.: \"3\"", "admin.service.minimumHashtagLengthTitle": "Minimum Hashtag Length:", "admin.service.mobileSessionHours": "Session Length Mobile (hours):", diff --git a/webapp/channels/src/packages/mattermost-redux/src/action_types/users.ts b/webapp/channels/src/packages/mattermost-redux/src/action_types/users.ts index bc0f8b3ea22..ba59d9e0ce4 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/action_types/users.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/action_types/users.ts @@ -39,8 +39,6 @@ export default keyMirror({ RECEIVED_PROFILE_NOT_IN_TEAM: null, RECEIVED_PROFILES_LIST_NOT_IN_TEAM: null, RECEIVED_PROFILES_LIST_NOT_IN_TEAM_AND_REPLACE: null, - RECEIVED_PROFILE_WITHOUT_TEAM: null, - RECEIVED_PROFILES_LIST_WITHOUT_TEAM: null, RECEIVED_PROFILES_IN_CHANNEL: null, RECEIVED_PROFILES_LIST_IN_CHANNEL: null, RECEIVED_PROFILE_IN_CHANNEL: null, diff --git a/webapp/channels/src/packages/mattermost-redux/src/actions/users.test.ts b/webapp/channels/src/packages/mattermost-redux/src/actions/users.test.ts index e58b8332b83..a43d8496f90 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/actions/users.test.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/actions/users.test.ts @@ -567,27 +567,6 @@ describe('Actions.Users', () => { expect(notInTeam.size > 0).toBeTruthy(); }); - it('getProfilesWithoutTeam', async () => { - nock(Client4.getBaseRoute()). - post('/users'). - reply(200, TestHelper.fakeUserWithId()); - - const user = await TestHelper.basicClient4!.createUser(TestHelper.fakeUser(), '', ''); - - nock(Client4.getBaseRoute()). - get('/users'). - query(true). - reply(200, [user]); - - await store.dispatch(Actions.getProfilesWithoutTeam(0)); - const {profilesWithoutTeam, profiles} = store.getState().entities.users; - - expect(profilesWithoutTeam).toBeTruthy(); - expect(profilesWithoutTeam.size > 0).toBeTruthy(); - expect(profiles).toBeTruthy(); - expect(Object.keys(profiles).length > 0).toBeTruthy(); - }); - it('getProfilesInChannel', async () => { nock(Client4.getBaseRoute()). get('/users'). diff --git a/webapp/channels/src/packages/mattermost-redux/src/actions/users.ts b/webapp/channels/src/packages/mattermost-redux/src/actions/users.ts index 39b45a0e907..4c80907277f 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/actions/users.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/actions/users.ts @@ -319,32 +319,6 @@ export function getProfilesNotInTeam(teamId: string, groupConstrained: boolean, }; } -export function getProfilesWithoutTeam(page: number, perPage: number = General.PROFILE_CHUNK_SIZE, options: any = {}): ActionFuncAsync { - return async (dispatch, getState) => { - let profiles = null; - try { - profiles = await Client4.getProfilesWithoutTeam(page, perPage, options); - } catch (error) { - forceLogoutIfNecessary(error, dispatch, getState); - dispatch(logError(error)); - return {error}; - } - - dispatch(batchActions([ - { - type: UserTypes.RECEIVED_PROFILES_LIST_WITHOUT_TEAM, - data: profiles, - }, - { - type: UserTypes.RECEIVED_PROFILES_LIST, - data: profiles, - }, - ])); - - return {data: profiles}; - }; -} - export enum ProfilesInChannelSortBy { None = '', Admin = 'admin', diff --git a/webapp/channels/src/packages/mattermost-redux/src/constants/preferences.ts b/webapp/channels/src/packages/mattermost-redux/src/constants/preferences.ts index 226f606b148..60ea89f7954 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/constants/preferences.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/constants/preferences.ts @@ -75,7 +75,6 @@ const Preferences = { CATEGORY_REPORTING: 'reporting', HIDE_BATCH_EXPORT_CONFIRM_MODAL: 'hide_batch_export_confirm_modal', - HIDE_MYSQL_STATS_NOTIFICATION: 'hide_mysql_stats_notifcation', CATEGORY_OVERAGE_USERS_BANNER: 'overage_users_banner', CATEGORY_POST_HISTORY_LIMIT_BANNER: 'post_history_limit_banner', diff --git a/webapp/channels/src/packages/mattermost-redux/src/reducers/entities/users.test.ts b/webapp/channels/src/packages/mattermost-redux/src/reducers/entities/users.test.ts index 27d82763cce..3289cf7344e 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/reducers/entities/users.test.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/reducers/entities/users.test.ts @@ -1203,7 +1203,6 @@ describe('Reducers.users', () => { profilesNotInTeam: { team2: new Set([user.id]), }, - profilesWithoutTeam: new Set([user.id]), profilesInChannel: { channel1: new Set([user.id]), }, @@ -1250,7 +1249,6 @@ describe('Reducers.users', () => { profilesNotInTeam: { team2: new Set(), }, - profilesWithoutTeam: new Set(), profilesInChannel: { channel1: new Set(), }, diff --git a/webapp/channels/src/packages/mattermost-redux/src/reducers/entities/users.ts b/webapp/channels/src/packages/mattermost-redux/src/reducers/entities/users.ts index 9d1d6cf3e05..046f21c0180 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/reducers/entities/users.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/reducers/entities/users.ts @@ -350,37 +350,6 @@ function profilesNotInTeam(state: UsersState['profilesNotInTeam'] = {}, action: } } -function profilesWithoutTeam(state: UsersState['profilesWithoutTeam'] = new Set(), action: MMReduxAction) { - switch (action.type) { - case UserTypes.RECEIVED_PROFILE_WITHOUT_TEAM: { - const nextSet = new Set(state); - Object.values(action.data as string[]).forEach((id: string) => nextSet.add(id)); - return nextSet; - } - case UserTypes.RECEIVED_PROFILES_LIST_WITHOUT_TEAM: { - const nextSet = new Set(state); - action.data.forEach((user: UserProfile) => nextSet.add(user.id)); - return nextSet; - } - case UserTypes.RECEIVED_PROFILE_IN_TEAM: { - const nextSet = new Set(state); - nextSet.delete(action.data.id); - return nextSet; - } - case UserTypes.PROFILE_NO_LONGER_VISIBLE: { - const nextSet = new Set(state); - nextSet.delete(action.data.user_id); - return nextSet; - } - - case UserTypes.LOGOUT_SUCCESS: - return new Set(); - - default: - return state; - } -} - function profilesInChannel(state: UsersState['profilesInChannel'] = {}, action: MMReduxAction) { switch (action.type) { case UserTypes.RECEIVED_PROFILE_IN_CHANNEL: @@ -716,9 +685,6 @@ export default combineReducers({ // object where every key is a team id and has a Set with the users id that are not members of the team profilesNotInTeam, - // set with user ids for users that are not on any team - profilesWithoutTeam, - // object where every key is a channel id and has a Set with the users id that are members of the channel profilesInChannel, diff --git a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.test.ts b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.test.ts index 9485f6f710b..73594136ece 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.test.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.test.ts @@ -74,8 +74,6 @@ describe('Selectors.Users', () => { const profilesNotInTeam: Record> = {}; profilesNotInTeam[team1.id] = new Set([user3.id, user4.id]); - const profilesWithoutTeam = new Set([user5.id, user6.id]); - const profilesInChannel: Record> = {}; profilesInChannel[channel1.id] = new Set([user1.id]); profilesInChannel[channel2.id] = new Set([user1.id, user2.id]); @@ -136,7 +134,6 @@ describe('Selectors.Users', () => { profiles, profilesInTeam, profilesNotInTeam, - profilesWithoutTeam, profilesInChannel, profilesNotInChannel, profilesInGroup, @@ -173,10 +170,6 @@ describe('Selectors.Users', () => { expect(Selectors.getUserIdsNotInTeams(testState)).toEqual(profilesNotInTeam); }); - it('getUserIdsWithoutTeam', () => { - expect(Selectors.getUserIdsWithoutTeam(testState)).toEqual(profilesWithoutTeam); - }); - it('getUserSessions', () => { expect(Selectors.getUserSessions(testState)).toEqual(userSessions); }); @@ -417,16 +410,6 @@ describe('Selectors.Users', () => { expect(Selectors.getProfilesNotInCurrentTeam(testState)).toEqual(users); }); - describe('getProfilesWithoutTeam', () => { - it('getProfilesWithoutTeam', () => { - const users = [user5, user6].sort(sortByUsername); - expect(Selectors.getProfilesWithoutTeam(testState, {} as any)).toEqual(users); - }); - it('getProfilesWithoutTeam with filter', () => { - expect(Selectors.getProfilesWithoutTeam(testState, {role: 'system_admin'})).toEqual([user6]); - }); - }); - it('getProfilesInGroup', () => { expect(Selectors.getProfilesInGroup(testState, group1.id)).toEqual([user1]); const users = [user2, user3].sort(sortByUsername); @@ -516,16 +499,6 @@ describe('Selectors.Users', () => { expect(Selectors.searchProfilesNotInCurrentTeam(testState, user3.username, true)).toEqual([user3]); }); - describe('searchProfilesWithoutTeam', () => { - it('searchProfilesWithoutTeam without filter', () => { - expect(Selectors.searchProfilesWithoutTeam(testState, user5.username, false, {})).toEqual([user5]); - expect(Selectors.searchProfilesWithoutTeam(testState, user5.username, true, {})).toEqual([user5]); - }); - it('searchProfilesWithoutTeam with filter', () => { - expect(Selectors.searchProfilesWithoutTeam(testState, user6.username, false, {role: 'system_admin'})).toEqual([user6]); - expect(Selectors.searchProfilesWithoutTeam(testState, user5.username, false, {inactive: true})).toEqual([]); - }); - }); it('searchProfilesInGroup', () => { expect(Selectors.searchProfilesInGroup(testState, group1.id, user5.username)).toEqual([]); expect(Selectors.searchProfilesInGroup(testState, group1.id, user1.username)).toEqual([user1]); diff --git a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.ts b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.ts index 86f984ab6d9..eb8faafeebc 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.ts @@ -72,10 +72,6 @@ export function getUserIdsNotInTeams(state: GlobalState): RelationOneToManyUniqu return state.entities.users.profilesNotInTeam; } -export function getUserIdsWithoutTeam(state: GlobalState): Set { - return state.entities.users.profilesWithoutTeam; -} - export function getUserIdsInGroups(state: GlobalState): RelationOneToManyUnique { return state.entities.users.profilesInGroup; } @@ -443,16 +439,6 @@ export const getProfilesNotInCurrentTeam: (state: GlobalState) => UserProfile[] }, ); -export const getProfilesWithoutTeam: (state: GlobalState, filters: Filters) => UserProfile[] = createSelector( - 'getProfilesWithoutTeam', - getUsers, - getUserIdsWithoutTeam, - (state: GlobalState, filters: Filters) => filters, - (profiles, withoutTeamProfileSet, filters) => { - return sortAndInjectProfiles(filterProfiles(profiles, filters), withoutTeamProfileSet); - }, -); - export function getStatusForUserId(state: GlobalState, userId: UserProfile['id']): string { return getUserStatuses(state)[userId]; } @@ -573,15 +559,6 @@ export function searchProfilesNotInCurrentTeam(state: GlobalState, term: string, return profiles; } -export function searchProfilesWithoutTeam(state: GlobalState, term: string, skipCurrent = false, filters: Filters): UserProfile[] { - const filteredProfiles = filterProfilesStartingWithTerm(getProfilesWithoutTeam(state, filters), term); - if (skipCurrent) { - removeCurrentUserFromList(filteredProfiles, getCurrentUserId(state)); - } - - return filteredProfiles; -} - function removeCurrentUserFromList(profiles: UserProfile[], currentUserId: UserProfile['id']) { const index = profiles.findIndex((p) => p.id === currentUserId); if (index >= 0) { diff --git a/webapp/channels/src/packages/mattermost-redux/src/store/initial_state.ts b/webapp/channels/src/packages/mattermost-redux/src/store/initial_state.ts index ee5521dcea6..ed19b0ed8d9 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/store/initial_state.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/store/initial_state.ts @@ -27,7 +27,6 @@ const state: GlobalState = { profiles: {}, profilesInTeam: {}, profilesNotInTeam: {}, - profilesWithoutTeam: new Set(), profilesInChannel: {}, profilesNotInChannel: {}, profilesInGroup: {}, diff --git a/webapp/channels/src/plugins/channel_header_plug/channel_header_plug.tsx b/webapp/channels/src/plugins/channel_header_plug/channel_header_plug.tsx index c102545e9a7..e7c90ffe47b 100644 --- a/webapp/channels/src/plugins/channel_header_plug/channel_header_plug.tsx +++ b/webapp/channels/src/plugins/channel_header_plug/channel_header_plug.tsx @@ -29,6 +29,9 @@ type CustomMenuProps = { children?: React.ReactNode; onClose: () => void; rootCloseEvent?: 'click' | 'mousedown'; + + // A bsRole prop is required by React Bootstrap's Dropdown + // eslint-disable-next-line react/no-unused-prop-types bsRole: string; } @@ -67,6 +70,9 @@ type CustomToggleProps = { children?: React.ReactNode; dropdownOpen?: boolean; onClick?: (e: React.MouseEvent) => void; + + // A bsRole prop is required by React Bootstrap's Dropdown + // eslint-disable-next-line react/no-unused-prop-types bsRole: string; } diff --git a/webapp/channels/src/tests/constants/users.ts b/webapp/channels/src/tests/constants/users.ts index 709af097596..67cfa992588 100644 --- a/webapp/channels/src/tests/constants/users.ts +++ b/webapp/channels/src/tests/constants/users.ts @@ -13,7 +13,6 @@ const emptyOtherUsersState: Omit; } -export type WarnMetricStatus = { - id: string; - limit: number; - acked: boolean; - store_status: string; -}; - export enum CollapsedThreads { DISABLED = 'disabled', DEFAULT_ON = 'default_on', diff --git a/webapp/platform/types/src/users.ts b/webapp/platform/types/src/users.ts index bc677843bb3..36aa62345dd 100644 --- a/webapp/platform/types/src/users.ts +++ b/webapp/platform/types/src/users.ts @@ -77,7 +77,6 @@ export type UsersState = { profiles: IDMappedObjects; profilesInTeam: RelationOneToManyUnique; profilesNotInTeam: RelationOneToManyUnique; - profilesWithoutTeam: Set; profilesInChannel: RelationOneToManyUnique; profilesNotInChannel: RelationOneToManyUnique; profilesInGroup: RelationOneToManyUnique;