From 5a872c3d6919bf164256bf750927dc9201ef8194 Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Tue, 24 Jan 2023 09:13:19 +0530 Subject: [PATCH 001/102] MM-49703: Bump to Go 1.19 (#4489) (#4502) (#4507) Also fix some gofmt issues https://mattermost.atlassian.net/browse/MM-49703 --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/dev-release.yml | 8 ++++---- .github/workflows/lint-server.yml | 4 ++-- .github/workflows/prod-release.yml | 8 ++++---- .gitlab-ci.yml | 2 +- build/gowork/main.go | 2 +- linux/go.mod | 2 +- mattermost-plugin/build/go.mod | 2 +- mattermost-plugin/go.mod | 2 +- server/.golangci.yml | 3 --- server/api/api.go | 4 ++-- server/api/audit.go | 2 +- server/api/auth.go | 5 +++-- server/api/members.go | 2 +- server/app/insights.go | 2 +- server/app/insights_test.go | 4 ++-- server/assets/assets.go | 1 + server/go.mod | 2 +- server/go.tools.mod | 2 +- server/integrationtests/cards_test.go | 2 -- server/main/main.go | 4 +++- server/server/server.go | 2 +- server/services/audit/audit.go | 8 +++++--- server/services/metrics/service.go | 2 +- .../store/mattermostauthlayer/mattermostauthlayer.go | 2 +- server/services/store/mockstore/mockstore.go | 8 ++++---- server/services/store/sqlstore/board_insights.go | 2 +- server/services/store/sqlstore/public_methods.go | 6 +++--- server/services/store/sqlstore/sqlstore.go | 4 ++-- server/services/store/store.go | 2 +- server/services/store/storetests/board_insights.go | 2 +- server/web/webserver.go | 3 ++- server/ws/plugin_adapter.go | 12 ++++++------ server/ws/plugin_adapter_cluster.go | 3 ++- 34 files changed, 65 insertions(+), 62 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 296435f5f..783c58582 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,7 +48,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.18.1 + go-version: 1.19.5 - name: "Test server: ${{matrix['db']}}" run: cd focalboard; make server-test-${{matrix['db']}} @@ -83,7 +83,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.18.1 + go-version: 1.19.5 - name: Setup Node uses: actions/setup-node@v3 @@ -137,7 +137,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.18.1 + go-version: 1.19.5 - name: "Test server (minimum): ${{matrix['db']}}" run: cd focalboard; make server-test-mini-${{matrix['db']}} @@ -174,7 +174,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.18.1 + go-version: 1.19.5 - name: "Test server (minimum): ${{matrix['db']}}" run: cd focalboard; make server-test-mini-${{matrix['db']}} diff --git a/.github/workflows/dev-release.yml b/.github/workflows/dev-release.yml index 2376c1f1d..9ebf34df6 100644 --- a/.github/workflows/dev-release.yml +++ b/.github/workflows/dev-release.yml @@ -54,7 +54,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.18.1 + go-version: 1.19.5 - name: Setup Node uses: actions/setup-node@v3 @@ -129,7 +129,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.18.1 + go-version: 1.19.5 - name: List Xcode versions run: ls -n /Applications/ | grep Xcode* @@ -190,7 +190,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.18.1 + go-version: 1.19.5 - name: Setup NuGet uses: nuget/setup-nuget@v1 @@ -258,7 +258,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.18.1 + go-version: 1.19.5 - name: Set up Node uses: actions/setup-node@v3 diff --git a/.github/workflows/lint-server.yml b/.github/workflows/lint-server.yml index eb5093406..3c114e71b 100644 --- a/.github/workflows/lint-server.yml +++ b/.github/workflows/lint-server.yml @@ -30,7 +30,7 @@ jobs: steps: - uses: actions/setup-go@v3 with: - go-version: 1.18.1 + go-version: 1.19.5 - uses: actions/checkout@v3 with: path: "focalboard" @@ -50,7 +50,7 @@ jobs: path: "mattermost-server" ref : "master" - name: set up golangci-lint - run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.46.2 + run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.50.1 - name: lint run: | cd focalboard diff --git a/.github/workflows/prod-release.yml b/.github/workflows/prod-release.yml index feb078617..8ca6f4f98 100644 --- a/.github/workflows/prod-release.yml +++ b/.github/workflows/prod-release.yml @@ -50,7 +50,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.18.1 + go-version: 1.19.5 - name: Setup Node uses: actions/setup-node@v3 @@ -126,7 +126,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.18.1 + go-version: 1.19.5 - name: List Xcode versions run: ls -n /Applications/ | grep Xcode* @@ -188,7 +188,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.18.1 + go-version: 1.19.5 - name: Setup NuGet uses: nuget/setup-nuget@v1 @@ -257,7 +257,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.18.1 + go-version: 1.19.5 - name: Set up Node uses: actions/setup-node@v3 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 09944dba2..f6107d60f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,7 +4,7 @@ stages: variables: BUILD: "yes" - IMAGE_BUILDER: $CI_REGISTRY/mattermost/ci/images/builder:go-1.18.1-node-16.15.0-1 + IMAGE_BUILDER: $CI_REGISTRY/mattermost/ci/images/builder:go-1.19.5-node-16.15.0-1 include: - project: mattermost/ci/focalboard diff --git a/build/gowork/main.go b/build/gowork/main.go index c962369d5..b8619ebdf 100644 --- a/build/gowork/main.go +++ b/build/gowork/main.go @@ -51,7 +51,7 @@ func makeGoWork(ci bool) string { var b strings.Builder - b.WriteString("go 1.18\n\n") + b.WriteString("go 1.19\n\n") b.WriteString("use ./server\n") for repo, envVarName := range repos { diff --git a/linux/go.mod b/linux/go.mod index b5a89f917..497722568 100644 --- a/linux/go.mod +++ b/linux/go.mod @@ -1,6 +1,6 @@ module github.com/mattermost/focalboard/linux -go 1.18 +go 1.19 replace github.com/mattermost/focalboard/server => ../server diff --git a/mattermost-plugin/build/go.mod b/mattermost-plugin/build/go.mod index 679c3003e..0ba2a34ef 100644 --- a/mattermost-plugin/build/go.mod +++ b/mattermost-plugin/build/go.mod @@ -1,6 +1,6 @@ module github.com/mattermost/mattermost-plugin-starter-template/build -go 1.18 +go 1.19 require ( github.com/go-git/go-git/v5 v5.1.0 diff --git a/mattermost-plugin/go.mod b/mattermost-plugin/go.mod index b36f6db8d..8e3fd146a 100644 --- a/mattermost-plugin/go.mod +++ b/mattermost-plugin/go.mod @@ -1,6 +1,6 @@ module github.com/mattermost/focalboard/mattermost-plugin -go 1.18 +go 1.19 require ( github.com/golang/mock v1.6.0 diff --git a/server/.golangci.yml b/server/.golangci.yml index c1381759f..23f4fce36 100644 --- a/server/.golangci.yml +++ b/server/.golangci.yml @@ -27,10 +27,7 @@ linters: enable: - gofmt - goimports - - deadcode - ineffassign - - structcheck - - varcheck - unparam - errcheck - govet diff --git a/server/api/api.go b/server/api/api.go index da87f0b24..3f3dcb418 100644 --- a/server/api/api.go +++ b/server/api/api.go @@ -220,7 +220,7 @@ func stringResponse(w http.ResponseWriter, message string) { _, _ = fmt.Fprint(w, message) } -func jsonStringResponse(w http.ResponseWriter, code int, message string) { +func jsonStringResponse(w http.ResponseWriter, code int, message string) { //nolint:unparam setResponseHeader(w, "Content-Type", "application/json") w.WriteHeader(code) fmt.Fprint(w, message) @@ -232,7 +232,7 @@ func jsonBytesResponse(w http.ResponseWriter, code int, json []byte) { _, _ = w.Write(json) } -func setResponseHeader(w http.ResponseWriter, key string, value string) { +func setResponseHeader(w http.ResponseWriter, key string, value string) { //nolint:unparam header := w.Header() if header == nil { return diff --git a/server/api/audit.go b/server/api/audit.go index dba563ffb..875f5c28c 100644 --- a/server/api/audit.go +++ b/server/api/audit.go @@ -8,7 +8,7 @@ import ( ) // makeAuditRecord creates an audit record pre-populated with data from the request. -func (a *API) makeAuditRecord(r *http.Request, event string, initialStatus string) *audit.Record { +func (a *API) makeAuditRecord(r *http.Request, event string, initialStatus string) *audit.Record { //nolint:unparam ctx := r.Context() var sessionID string var userID string diff --git a/server/api/auth.go b/server/api/auth.go index dffe86f18..b81660ab2 100644 --- a/server/api/auth.go +++ b/server/api/auth.go @@ -383,12 +383,13 @@ func (a *API) attachSession(handler func(w http.ResponseWriter, r *http.Request) authService := session.AuthService if authService != a.authService { - a.logger.Error(`Session authService mismatch`, + msg := `Session authService mismatch` + a.logger.Error(msg, mlog.String("sessionID", session.ID), mlog.String("want", a.authService), mlog.String("got", authService), ) - a.errorResponse(w, r, model.NewErrUnauthorized(err.Error())) + a.errorResponse(w, r, model.NewErrUnauthorized(msg)) return } diff --git a/server/api/members.go b/server/api/members.go index 3b5dff592..2014b84f3 100644 --- a/server/api/members.go +++ b/server/api/members.go @@ -146,7 +146,7 @@ func (a *API) handleAddMember(w http.ResponseWriter, r *http.Request) { } if reqBoardMember.UserID == "" { - a.errorResponse(w, r, model.NewErrBadRequest(err.Error())) + a.errorResponse(w, r, model.NewErrBadRequest("empty userID")) return } diff --git a/server/app/insights.go b/server/app/insights.go index 28027d54d..9179a86c2 100644 --- a/server/app/insights.go +++ b/server/app/insights.go @@ -19,7 +19,7 @@ func (a *App) GetTeamBoardsInsights(userID string, teamID string, opts *mmModel. if err != nil { return nil, err } - return a.store.GetTeamBoardsInsights(teamID, userID, opts.StartUnixMilli, opts.Page*opts.PerPage, opts.PerPage, boardIDs) + return a.store.GetTeamBoardsInsights(teamID, opts.StartUnixMilli, opts.Page*opts.PerPage, opts.PerPage, boardIDs) } func (a *App) GetUserBoardsInsights(userID string, teamID string, opts *mmModel.InsightsOpts) (*model.BoardInsightsList, error) { diff --git a/server/app/insights_test.go b/server/app/insights_test.go index 9a419c79e..c6897ff24 100644 --- a/server/app/insights_test.go +++ b/server/app/insights_test.go @@ -51,7 +51,7 @@ func TestGetTeamAndUserBoardsInsights(t *testing.T) { th.Store.EXPECT().GetUserByID("user-id").Return(fakeUser, nil).AnyTimes() th.Store.EXPECT().GetBoardsForUserAndTeam("user-id", "team-id", true).Return(mockInsightsBoards, nil).AnyTimes() th.Store.EXPECT(). - GetTeamBoardsInsights("team-id", "user-id", int64(0), 0, 10, []string{"mock-user-workspace-id"}). + GetTeamBoardsInsights("team-id", int64(0), 0, 10, []string{"mock-user-workspace-id"}). Return(mockTeamInsightsList, nil) results, err := th.App.GetTeamBoardsInsights("user-id", "team-id", &mmModel.InsightsOpts{StartUnixMilli: 0, Page: 0, PerPage: 10}) require.NoError(t, err) @@ -74,7 +74,7 @@ func TestGetTeamAndUserBoardsInsights(t *testing.T) { th.Store.EXPECT().GetUserByID("user-id").Return(fakeUser, nil).AnyTimes() th.Store.EXPECT().GetBoardsForUserAndTeam("user-id", "team-id", true).Return(mockInsightsBoards, nil).AnyTimes() th.Store.EXPECT(). - GetTeamBoardsInsights("team-id", "user-id", int64(0), 0, 10, []string{"mock-user-workspace-id"}). + GetTeamBoardsInsights("team-id", int64(0), 0, 10, []string{"mock-user-workspace-id"}). Return(nil, insightError{"board-insight-error"}) _, err := th.App.GetTeamBoardsInsights("user-id", "team-id", &mmModel.InsightsOpts{StartUnixMilli: 0, Page: 0, PerPage: 10}) require.Error(t, err) diff --git a/server/assets/assets.go b/server/assets/assets.go index 4eeecefb9..b558d4e80 100644 --- a/server/assets/assets.go +++ b/server/assets/assets.go @@ -7,5 +7,6 @@ import ( // DefaultTemplatesArchive is an embedded archive file containing the default // templates to be imported to team 0. // This archive is generated with `make templates-archive` +// //go:embed templates.boardarchive var DefaultTemplatesArchive []byte diff --git a/server/go.mod b/server/go.mod index 6dd50b088..fa923cb1c 100644 --- a/server/go.mod +++ b/server/go.mod @@ -1,6 +1,6 @@ module github.com/mattermost/focalboard/server -go 1.18 +go 1.19 require ( github.com/Masterminds/squirrel v1.5.3 diff --git a/server/go.tools.mod b/server/go.tools.mod index 32450070e..ee3a74487 100644 --- a/server/go.tools.mod +++ b/server/go.tools.mod @@ -1,6 +1,6 @@ module github.com/mattermost/focalboard/server -go 1.18 +go 1.19 require github.com/golang/mock v1.6.0 diff --git a/server/integrationtests/cards_test.go b/server/integrationtests/cards_test.go index 8cd51fd59..a6ec5f7d8 100644 --- a/server/integrationtests/cards_test.go +++ b/server/integrationtests/cards_test.go @@ -269,9 +269,7 @@ func TestGetCard(t *testing.T) { }) } -// // Helpers. -// func reverse(src []string) []string { out := make([]string, 0, len(src)) for i := len(src) - 1; i >= 0; i-- { diff --git a/server/main/main.go b/server/main/main.go index ba7298f91..31eaa7d14 100644 --- a/server/main/main.go +++ b/server/main/main.go @@ -122,7 +122,7 @@ func main() { if pDBConfig != nil && len(*pDBConfig) > 0 { config.DBConfigString = *pDBConfig // Don't echo, as the confix string may contain passwords - logger.Info("DBConfigString overriden from commandline") + logger.Info("DBConfigString overridden from commandline") } if pPort != nil && *pPort > 0 && *pPort != config.Port { @@ -166,6 +166,7 @@ func main() { } // StartServer starts the server +// //export StartServer func StartServer(webPath *C.char, filesPath *C.char, port int, singleUserToken, dbConfigString, configFilePath *C.char) { startServer( @@ -179,6 +180,7 @@ func StartServer(webPath *C.char, filesPath *C.char, port int, singleUserToken, } // StopServer stops the server +// //export StopServer func StopServer() { stopServer() diff --git a/server/server/server.go b/server/server/server.go index fa72b42fa..b7e939c1c 100644 --- a/server/server/server.go +++ b/server/server/server.go @@ -377,7 +377,7 @@ func (s *Server) UpdateAppConfig() { // Local server func (s *Server) startLocalModeServer() error { - s.localModeServer = &http.Server{ + s.localModeServer = &http.Server{ //nolint:gosec Handler: s.localRouter, ConnContext: api.SetContextConn, } diff --git a/server/services/audit/audit.go b/server/services/audit/audit.go index 51b196b1e..cfb240097 100644 --- a/server/services/audit/audit.go +++ b/server/services/audit/audit.go @@ -46,12 +46,14 @@ func NewAudit(options ...mlog.Option) (*Audit, error) { // Configure provides a new configuration for this audit service. // Zero or more sources of config can be provided: -// cfgFile - path to file containing JSON -// cfgEscaped - JSON string probably from ENV var +// +// cfgFile - path to file containing JSON +// cfgEscaped - JSON string probably from ENV var // // For each case JSON containing log targets is provided. Target name collisions are resolved // using the following precedence: -// cfgFile > cfgEscaped +// +// cfgFile > cfgEscaped func (a *Audit) Configure(cfgFile string, cfgEscaped string) error { return a.auditLogger.Configure(cfgFile, cfgEscaped, nil) } diff --git a/server/services/metrics/service.go b/server/services/metrics/service.go index 5345e1f03..415da04b6 100644 --- a/server/services/metrics/service.go +++ b/server/services/metrics/service.go @@ -17,7 +17,7 @@ type Service struct { // NewMetricsServer factory method to create a new prometheus server. func NewMetricsServer(address string, metricsService *Metrics, logger mlog.LoggerIFace) *Service { return &Service{ - &http.Server{ + &http.Server{ //nolint:gosec Addr: address, Handler: promhttp.HandlerFor(metricsService.registry, promhttp.HandlerOpts{ ErrorLog: logger.StdLogger(mlog.LvlError), diff --git a/server/services/store/mattermostauthlayer/mattermostauthlayer.go b/server/services/store/mattermostauthlayer/mattermostauthlayer.go index d2b86e893..2696b382c 100644 --- a/server/services/store/mattermostauthlayer/mattermostauthlayer.go +++ b/server/services/store/mattermostauthlayer/mattermostauthlayer.go @@ -599,7 +599,7 @@ func (s *MattermostAuthLayer) GetLicense() *mmModel.License { return s.servicesAPI.GetLicense() } -func boardFields(prefix string) []string { +func boardFields(prefix string) []string { //nolint:unparam fields := []string{ "id", "team_id", diff --git a/server/services/store/mockstore/mockstore.go b/server/services/store/mockstore/mockstore.go index 63813e7a7..be3c588d4 100644 --- a/server/services/store/mockstore/mockstore.go +++ b/server/services/store/mockstore/mockstore.go @@ -999,18 +999,18 @@ func (mr *MockStoreMockRecorder) GetTeam(arg0 interface{}) *gomock.Call { } // GetTeamBoardsInsights mocks base method. -func (m *MockStore) GetTeamBoardsInsights(arg0, arg1 string, arg2 int64, arg3, arg4 int, arg5 []string) (*model.BoardInsightsList, error) { +func (m *MockStore) GetTeamBoardsInsights(arg0 string, arg1 int64, arg2, arg3 int, arg4 []string) (*model.BoardInsightsList, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetTeamBoardsInsights", arg0, arg1, arg2, arg3, arg4, arg5) + ret := m.ctrl.Call(m, "GetTeamBoardsInsights", arg0, arg1, arg2, arg3, arg4) ret0, _ := ret[0].(*model.BoardInsightsList) ret1, _ := ret[1].(error) return ret0, ret1 } // GetTeamBoardsInsights indicates an expected call of GetTeamBoardsInsights. -func (mr *MockStoreMockRecorder) GetTeamBoardsInsights(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) GetTeamBoardsInsights(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTeamBoardsInsights", reflect.TypeOf((*MockStore)(nil).GetTeamBoardsInsights), arg0, arg1, arg2, arg3, arg4, arg5) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTeamBoardsInsights", reflect.TypeOf((*MockStore)(nil).GetTeamBoardsInsights), arg0, arg1, arg2, arg3, arg4) } // GetTeamCount mocks base method. diff --git a/server/services/store/sqlstore/board_insights.go b/server/services/store/sqlstore/board_insights.go index 73c92c9f6..8f4dad92e 100644 --- a/server/services/store/sqlstore/board_insights.go +++ b/server/services/store/sqlstore/board_insights.go @@ -14,7 +14,7 @@ import ( "github.com/mattermost/mattermost-server/v6/shared/mlog" ) -func (s *SQLStore) getTeamBoardsInsights(db sq.BaseRunner, teamID string, userID string, since int64, offset int, limit int, boardIDs []string) (*model.BoardInsightsList, error) { +func (s *SQLStore) getTeamBoardsInsights(db sq.BaseRunner, teamID string, since int64, offset int, limit int, boardIDs []string) (*model.BoardInsightsList, error) { boardsHistoryQuery := s.getQueryBuilder(db). Select("boards.id, boards.icon, boards.title, count(boards_history.id) as count, boards_history.modified_by, boards.created_by"). From(s.tablePrefix + "boards_history as boards_history"). diff --git a/server/services/store/sqlstore/public_methods.go b/server/services/store/sqlstore/public_methods.go index e3acf4955..e484d676a 100644 --- a/server/services/store/sqlstore/public_methods.go +++ b/server/services/store/sqlstore/public_methods.go @@ -144,7 +144,7 @@ func (s *SQLStore) CreateUser(user *model.User) (*model.User, error) { } func (s *SQLStore) DBVersion() string { - return s.dBVersion(s.db) + return s.dBVersion() } @@ -513,8 +513,8 @@ func (s *SQLStore) GetTeam(ID string) (*model.Team, error) { } -func (s *SQLStore) GetTeamBoardsInsights(teamID string, userID string, since int64, offset int, limit int, boardIDs []string) (*model.BoardInsightsList, error) { - return s.getTeamBoardsInsights(s.db, teamID, userID, since, offset, limit, boardIDs) +func (s *SQLStore) GetTeamBoardsInsights(teamID string, since int64, offset int, limit int, boardIDs []string) (*model.BoardInsightsList, error) { + return s.getTeamBoardsInsights(s.db, teamID, since, offset, limit, boardIDs) } diff --git a/server/services/store/sqlstore/sqlstore.go b/server/services/store/sqlstore/sqlstore.go index 854886d8d..7d7f36ade 100644 --- a/server/services/store/sqlstore/sqlstore.go +++ b/server/services/store/sqlstore/sqlstore.go @@ -136,7 +136,7 @@ func (s *SQLStore) getQueryBuilder(db sq.BaseRunner) sq.StatementBuilderType { return builder.RunWith(db) } -func (s *SQLStore) escapeField(fieldName string) string { +func (s *SQLStore) escapeField(fieldName string) string { //nolint:unparam if s.dbType == model.MysqlDBType { return "`" + fieldName + "`" } @@ -185,7 +185,7 @@ func (s *SQLStore) getChannel(db sq.BaseRunner, teamID, channel string) (*mmMode return nil, store.NewNotSupportedError("get channel not supported on standalone mode") } -func (s *SQLStore) dBVersion(db sq.BaseRunner) string { +func (s *SQLStore) dBVersion() string { var version string var row *sql.Row diff --git a/server/services/store/store.go b/server/services/store/store.go index ac1f4fc37..eb9fabedb 100644 --- a/server/services/store/store.go +++ b/server/services/store/store.go @@ -168,7 +168,7 @@ type Store interface { SendMessage(message, postType string, receipts []string) error // Insights - GetTeamBoardsInsights(teamID string, userID string, since int64, offset int, limit int, boardIDs []string) (*model.BoardInsightsList, error) + GetTeamBoardsInsights(teamID string, since int64, offset int, limit int, boardIDs []string) (*model.BoardInsightsList, error) GetUserBoardsInsights(teamID string, userID string, since int64, offset int, limit int, boardIDs []string) (*model.BoardInsightsList, error) GetUserTimezone(userID string) (string, error) diff --git a/server/services/store/storetests/board_insights.go b/server/services/store/storetests/board_insights.go index 85470cd47..f13091568 100644 --- a/server/services/store/storetests/board_insights.go +++ b/server/services/store/storetests/board_insights.go @@ -72,7 +72,7 @@ func getBoardsInsightsTest(t *testing.T, store store.Store) { boardsUser2, _ := store.GetBoardsForUserAndTeam(testInsightsUserID1, testTeamID, true) t.Run("team insights", func(t *testing.T) { boardIDs := []string{boardsUser1[0].ID, boardsUser1[1].ID, boardsUser1[2].ID} - topTeamBoards, err := store.GetTeamBoardsInsights(testTeamID, testUserID, + topTeamBoards, err := store.GetTeamBoardsInsights(testTeamID, 0, 0, 10, boardIDs) require.NoError(t, err) require.Len(t, topTeamBoards.Items, 3) diff --git a/server/web/webserver.go b/server/web/webserver.go index 237c7f40f..ad0539078 100644 --- a/server/web/webserver.go +++ b/server/web/webserver.go @@ -59,7 +59,8 @@ func NewServer(rootPath string, serverRoot string, port int, ssl, localOnly bool baseURL = url.Path ws := &Server{ - Server: http.Server{ + // (TODO: Add ReadHeaderTimeout) + Server: http.Server{ //nolint:gosec Addr: addr, Handler: r, }, diff --git a/server/ws/plugin_adapter.go b/server/ws/plugin_adapter.go index f45cae629..65cafb09b 100644 --- a/server/ws/plugin_adapter.go +++ b/server/ws/plugin_adapter.go @@ -422,7 +422,7 @@ func (pa *PluginAdapter) sendTeamMessage(event, teamID string, payload map[strin EnsureUsers: ensureUserIDs, } - pa.sendMessageToCluster("websocket_message", clusterMessage) + pa.sendMessageToCluster(clusterMessage) }() pa.sendTeamMessageSkipCluster(event, teamID, payload) @@ -447,7 +447,7 @@ func (pa *PluginAdapter) sendBoardMessage(teamID, boardID string, payload map[st EnsureUsers: ensureUserIDs, } - pa.sendMessageToCluster("websocket_message", clusterMessage) + pa.sendMessageToCluster(clusterMessage) }() pa.sendBoardMessageSkipCluster(teamID, boardID, payload, ensureUserIDs...) @@ -490,7 +490,7 @@ func (pa *PluginAdapter) BroadcastCategoryChange(category model.Category) { UserID: category.UserID, } - pa.sendMessageToCluster("websocket_message", clusterMessage) + pa.sendMessageToCluster(clusterMessage) }() pa.sendUserMessageSkipCluster(websocketActionUpdateCategory, payload, category.UserID) @@ -514,7 +514,7 @@ func (pa *PluginAdapter) BroadcastCategoryReorder(teamID, userID string, categor UserID: userID, } - pa.sendMessageToCluster("websocket_message", clusterMessage) + pa.sendMessageToCluster(clusterMessage) }() pa.sendUserMessageSkipCluster(message.Action, payload, userID) @@ -540,7 +540,7 @@ func (pa *PluginAdapter) BroadcastCategoryBoardsReorder(teamID, userID, category UserID: userID, } - pa.sendMessageToCluster("websocket_message", clusterMessage) + pa.sendMessageToCluster(clusterMessage) }() pa.sendUserMessageSkipCluster(message.Action, payload, userID) @@ -568,7 +568,7 @@ func (pa *PluginAdapter) BroadcastCategoryBoardChange(teamID, userID string, boa UserID: userID, } - pa.sendMessageToCluster("websocket_message", clusterMessage) + pa.sendMessageToCluster(clusterMessage) }() pa.sendUserMessageSkipCluster(websocketActionUpdateCategoryBoard, utils.StructToMap(message), userID) diff --git a/server/ws/plugin_adapter_cluster.go b/server/ws/plugin_adapter_cluster.go index 754b86afa..f326a61b7 100644 --- a/server/ws/plugin_adapter_cluster.go +++ b/server/ws/plugin_adapter_cluster.go @@ -15,7 +15,8 @@ type ClusterMessage struct { EnsureUsers []string } -func (pa *PluginAdapter) sendMessageToCluster(id string, clusterMessage *ClusterMessage) { +func (pa *PluginAdapter) sendMessageToCluster(clusterMessage *ClusterMessage) { + const id = "websocket_message" b, err := json.Marshal(clusterMessage) if err != nil { pa.logger.Error("couldn't get JSON bytes from cluster message", From 0cdad1f41d8cc2002e7c265702099dcd4e418547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20V=C3=A9lez=20Vidal?= Date: Wed, 1 Feb 2023 15:30:14 +0100 Subject: [PATCH 002/102] MM-48246 - ab test open RHS with linked board; add telemetry info --- .../webapp/src/components/rhsChannelBoardItem.tsx | 13 ++++++++++++- webapp/src/telemetry/telemetryClient.ts | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/mattermost-plugin/webapp/src/components/rhsChannelBoardItem.tsx b/mattermost-plugin/webapp/src/components/rhsChannelBoardItem.tsx index 5f60e71a8..43ee7841d 100644 --- a/mattermost-plugin/webapp/src/components/rhsChannelBoardItem.tsx +++ b/mattermost-plugin/webapp/src/components/rhsChannelBoardItem.tsx @@ -6,6 +6,7 @@ import {FormattedMessage, useIntl} from 'react-intl' import mutator from '../../../../webapp/src/mutator' import {Utils} from '../../../../webapp/src/utils' import {getCurrentTeam} from '../../../../webapp/src/store/teams' +import {getCurrentChannel} from '../../../../webapp/src/store/channels' import {createBoard, Board} from '../../../../webapp/src/blocks/board' import {useAppSelector} from '../../../../webapp/src/store/hooks' import IconButton from '../../../../webapp/src/widgets/buttons/iconButton' @@ -17,8 +18,10 @@ import CompassIcon from '../../../../webapp/src/widgets/icons/compassIcon' import {Permission} from '../../../../webapp/src/constants' -import './rhsChannelBoardItem.scss' import BoardPermissionGate from '../../../../webapp/src/components/permissions/boardPermissionGate' +import TelemetryClient, {TelemetryActions, TelemetryCategory} from '../../../../webapp/src/telemetry/telemetryClient' + +import './rhsChannelBoardItem.scss' const windowAny = (window as SuiteWindow) @@ -35,7 +38,15 @@ const RHSChannelBoardItem = (props: Props) => { return null } + const currentChannel = useAppSelector(getCurrentChannel) + if (!currentChannel) { + return null + } + const handleBoardClicked = (boardID: string) => { + // send the telemetry information for the clicked board + TelemetryClient.trackEvent(TelemetryCategory, TelemetryActions.ClickChannelsRHSBoard, {teamID: team.id, channelID: currentChannel.id}) + window.open(`${windowAny.frontendBaseURL}/team/${team.id}/${boardID}`, '_blank', 'noopener') } diff --git a/webapp/src/telemetry/telemetryClient.ts b/webapp/src/telemetry/telemetryClient.ts index 460e9d247..1787315da 100644 --- a/webapp/src/telemetry/telemetryClient.ts +++ b/webapp/src/telemetry/telemetryClient.ts @@ -50,6 +50,7 @@ export const TelemetryActions = { LimitCardLimitReached: 'limit_cardLimitReached', LimitCardLimitLinkOpen: 'limit_cardLimitLinkOpen', VersionMoreInfo: 'version_more_info', + ClickChannelsRHSBoard: 'click_channels_RHS_board', } interface IEventProps { From b4ea125a63ab10133ad3f97849c7687dd7bf5397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20V=C3=A9lez=20Vidal?= Date: Wed, 1 Feb 2023 18:53:02 +0100 Subject: [PATCH 003/102] add board info --- .../webapp/src/components/rhsChannelBoardItem.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mattermost-plugin/webapp/src/components/rhsChannelBoardItem.tsx b/mattermost-plugin/webapp/src/components/rhsChannelBoardItem.tsx index 43ee7841d..e796af1e5 100644 --- a/mattermost-plugin/webapp/src/components/rhsChannelBoardItem.tsx +++ b/mattermost-plugin/webapp/src/components/rhsChannelBoardItem.tsx @@ -45,7 +45,8 @@ const RHSChannelBoardItem = (props: Props) => { const handleBoardClicked = (boardID: string) => { // send the telemetry information for the clicked board - TelemetryClient.trackEvent(TelemetryCategory, TelemetryActions.ClickChannelsRHSBoard, {teamID: team.id, channelID: currentChannel.id}) + const extraData = {teamID: team.id, channelID: currentChannel.id, board: boardID} + TelemetryClient.trackEvent(TelemetryCategory, TelemetryActions.ClickChannelsRHSBoard, extraData) window.open(`${windowAny.frontendBaseURL}/team/${team.id}/${boardID}`, '_blank', 'noopener') } From 4030866a286c77ee14de1961f215a3336a9c498a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20V=C3=A9lez=20Vidal?= Date: Mon, 6 Feb 2023 14:31:25 +0100 Subject: [PATCH 004/102] remove innecessary telemetry channel information --- .../webapp/src/components/rhsChannelBoardItem.tsx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/mattermost-plugin/webapp/src/components/rhsChannelBoardItem.tsx b/mattermost-plugin/webapp/src/components/rhsChannelBoardItem.tsx index e796af1e5..1f03dc003 100644 --- a/mattermost-plugin/webapp/src/components/rhsChannelBoardItem.tsx +++ b/mattermost-plugin/webapp/src/components/rhsChannelBoardItem.tsx @@ -6,7 +6,6 @@ import {FormattedMessage, useIntl} from 'react-intl' import mutator from '../../../../webapp/src/mutator' import {Utils} from '../../../../webapp/src/utils' import {getCurrentTeam} from '../../../../webapp/src/store/teams' -import {getCurrentChannel} from '../../../../webapp/src/store/channels' import {createBoard, Board} from '../../../../webapp/src/blocks/board' import {useAppSelector} from '../../../../webapp/src/store/hooks' import IconButton from '../../../../webapp/src/widgets/buttons/iconButton' @@ -38,14 +37,9 @@ const RHSChannelBoardItem = (props: Props) => { return null } - const currentChannel = useAppSelector(getCurrentChannel) - if (!currentChannel) { - return null - } - const handleBoardClicked = (boardID: string) => { // send the telemetry information for the clicked board - const extraData = {teamID: team.id, channelID: currentChannel.id, board: boardID} + const extraData = {teamID: team.id, board: boardID} TelemetryClient.trackEvent(TelemetryCategory, TelemetryActions.ClickChannelsRHSBoard, extraData) window.open(`${windowAny.frontendBaseURL}/team/${team.id}/${boardID}`, '_blank', 'noopener') From 5b1c53dffa7bb70fbaeb2fe6040a23df12706037 Mon Sep 17 00:00:00 2001 From: Benjamin Cooke Date: Wed, 22 Feb 2023 16:21:12 -0500 Subject: [PATCH 005/102] updating date when prop has changed --- webapp/src/properties/date/date.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/webapp/src/properties/date/date.tsx b/webapp/src/properties/date/date.tsx index 23d764a1b..e2c285b5e 100644 --- a/webapp/src/properties/date/date.tsx +++ b/webapp/src/properties/date/date.tsx @@ -1,6 +1,6 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React, {useMemo, useState, useCallback} from 'react' +import React, {useMemo, useState, useCallback, useEffect} from 'react' import {useIntl} from 'react-intl' import {DateUtils} from 'react-day-picker' import MomentLocaleUtils from 'react-day-picker/moment' @@ -58,6 +58,12 @@ function DateRange(props: PropertyProps): JSX.Element { const [value, setValue] = useState(propertyValue) const intl = useIntl() + useEffect(() => { + if (value !== propertyValue) { + setValue(propertyValue) + } + }, [propertyValue, setValue]) + const onChange = useCallback((newValue) => { if (value !== newValue) { setValue(newValue) From ae44d6f2bfc78d36e9060a9c52ac8945695822c9 Mon Sep 17 00:00:00 2001 From: Benjamin Cooke Date: Thu, 23 Feb 2023 14:27:52 -0500 Subject: [PATCH 006/102] unit test --- .../date/__snapshots__/date.test.tsx.snap | 17 ++++++++++ webapp/src/properties/date/date.test.tsx | 32 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/webapp/src/properties/date/__snapshots__/date.test.tsx.snap b/webapp/src/properties/date/__snapshots__/date.test.tsx.snap index 861e203c5..231f47e8a 100644 --- a/webapp/src/properties/date/__snapshots__/date.test.tsx.snap +++ b/webapp/src/properties/date/__snapshots__/date.test.tsx.snap @@ -34,6 +34,23 @@ exports[`properties/dateRange handle clear 1`] = ` `; +exports[`properties/dateRange returns component with new date after prop change 1`] = ` +
+
+ +
+
+`; + exports[`properties/dateRange returns default correctly 1`] = `
{ expect(mockedMutator.changePropertyValue).toHaveBeenCalledWith(board.id, card, propertyTemplate.id, JSON.stringify({from: today})) }) + + test('returns component with new date after prop change', () => { + const component = wrapIntl( + , + ) + + const {container, rerender} = render(component) + + rerender( + wrapIntl( + + ) + ) + + expect(container).toMatchSnapshot() + }) }) From 30c9da952efa2aff4c2c1e817cdddcb2ba1bbc09 Mon Sep 17 00:00:00 2001 From: Benjamin Cooke Date: Thu, 23 Feb 2023 15:35:04 -0500 Subject: [PATCH 007/102] lint --- webapp/src/properties/date/date.test.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/webapp/src/properties/date/date.test.tsx b/webapp/src/properties/date/date.test.tsx index d1989425b..dfabdf706 100644 --- a/webapp/src/properties/date/date.test.tsx +++ b/webapp/src/properties/date/date.test.tsx @@ -315,7 +315,7 @@ describe('properties/dateRange', () => { expect(mockedMutator.changePropertyValue).toHaveBeenCalledWith(board.id, card, propertyTemplate.id, JSON.stringify({from: today})) }) - + test('returns component with new date after prop change', () => { const component = wrapIntl( { board={{...board}} card={{...card}} propertyTemplate={propertyTemplate} - /> - ) + />, + ), ) expect(container).toMatchSnapshot() From 8f3407291d7eee1864169d3b792f653b9b9bb3a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20V=C3=A9lez=20Vidal?= Date: Wed, 1 Mar 2023 00:34:43 +0100 Subject: [PATCH 008/102] update telemetry id Co-authored-by: Maria A Nunez --- webapp/src/telemetry/telemetryClient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/src/telemetry/telemetryClient.ts b/webapp/src/telemetry/telemetryClient.ts index 1787315da..c722929ff 100644 --- a/webapp/src/telemetry/telemetryClient.ts +++ b/webapp/src/telemetry/telemetryClient.ts @@ -50,7 +50,7 @@ export const TelemetryActions = { LimitCardLimitReached: 'limit_cardLimitReached', LimitCardLimitLinkOpen: 'limit_cardLimitLinkOpen', VersionMoreInfo: 'version_more_info', - ClickChannelsRHSBoard: 'click_channels_RHS_board', + ClickChannelsRHSBoard: 'click_board_in_channels_RHS', } interface IEventProps { From 73b8f0740640e1bfe11eefb9be1509579a0d9feb Mon Sep 17 00:00:00 2001 From: Benjamin Calisto Date: Mon, 27 Feb 2023 16:23:59 +0100 Subject: [PATCH 009/102] Translated using Weblate (Spanish) Currently translated at 48.6% (219 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/es/ --- webapp/i18n/es.json | 88 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 11 deletions(-) diff --git a/webapp/i18n/es.json b/webapp/i18n/es.json index da03bb0d1..9de79aac9 100644 --- a/webapp/i18n/es.json +++ b/webapp/i18n/es.json @@ -1,4 +1,15 @@ { + "AppBar.Tooltip": "Alternar tableros vinculados", + "Attachment.Attachment-title": "Archivos adjuntos", + "AttachmentBlock.DeleteAction": "borrar", + "AttachmentBlock.addElement": "agregar {type}", + "AttachmentBlock.delete": "Archivo adjunto eliminado.", + "AttachmentBlock.failed": "Este archivo no puede subirse debido a que excede el límite de tamaño de archivo.", + "AttachmentBlock.upload": "Subiendo archivo adjunto.", + "AttachmentBlock.uploadSuccess": "Archivo adjunto subido.", + "AttachmentElement.delete-confirmation-dialog-button-text": "Borrar", + "AttachmentElement.download": "Descargar", + "AttachmentElement.upload-percentage": "Subiendo...({uploadPercent}%)", "BoardComponent.add-a-group": "+ Añadir un grupo", "BoardComponent.delete": "Borrar", "BoardComponent.hidden-columns": "Columnas Ocultas", @@ -10,21 +21,39 @@ "BoardMember.schemeAdmin": "Administrador", "BoardMember.schemeEditor": "Editor", "BoardMember.schemeNone": "Ninguno", - "BoardPage.newVersion": "Una nueva versión de Board está disponible, haz click aquí para recargar.", - "BoardPage.syncFailed": "El tablero puede estar eliminado o el acceso fue revocado.", - "BoardTemplateSelector.add-template": "Nueva plantilla", - "BoardTemplateSelector.create-empty-board": "Crear pizarra vacía", - "BoardTemplateSelector.delete-template": "Suprimir", + "BoardMember.schemeViewer": "Visualizador", + "BoardMember.unlinkChannel": "Desvincular", + "BoardPage.newVersion": "Una nueva versión de Boards está disponible, haz clic aquí para recargar.", + "BoardPage.syncFailed": "El tablero puede haber sido eliminado o el acceso revocado.", + "BoardTemplateSelector.add-template": "Crear nueva plantilla", + "BoardTemplateSelector.create-empty-board": "Crear un tablero vacío", + "BoardTemplateSelector.delete-template": "Eliminar", + "BoardTemplateSelector.description": "Agregar un tablero a la barra lateral usando alguna de las plantillas definidas a continuación o empezar desde cero.", "BoardTemplateSelector.edit-template": "Editar", + "BoardTemplateSelector.plugin.no-content-description": "Agregar un tablero a la barra lateral usando alguna de las plantillas definidas a continuación o empezar desde cero.", + "BoardTemplateSelector.plugin.no-content-title": "Crear un tablero", + "BoardTemplateSelector.title": "Crear un tablero", "BoardTemplateSelector.use-this-template": "Utiliza esta plantilla", + "BoardsSwitcher.Title": "Encontrar tableros", + "BoardsUnfurl.Limited": "Los detalles adicionales están ocultos debido a que la tarjeta ha sido archivada", "BoardsUnfurl.Updated": "Actualizado {time}", - "Calculations.Options.count.displayName": "Cantidad", - "Calculations.Options.count.label": "Cantidad", + "Calculations.Options.average.displayName": "Promedio", + "Calculations.Options.average.label": "Promedio", + "Calculations.Options.count.displayName": "Contar", + "Calculations.Options.count.label": "Contar", "Calculations.Options.countChecked.displayName": "Marcado", + "Calculations.Options.countChecked.label": "Contar marcados", "Calculations.Options.countUnchecked.displayName": "Deseleccionado", + "Calculations.Options.countUnchecked.label": "Contar no marcados", + "Calculations.Options.countUniqueValue.displayName": "Único", + "Calculations.Options.countUniqueValue.label": "Contar valores únicos", "Calculations.Options.countValue.displayName": "Valores", "Calculations.Options.dateRange.displayName": "Rango", "Calculations.Options.dateRange.label": "Rango", + "Calculations.Options.earliest.displayName": "Más antiguo", + "Calculations.Options.earliest.label": "Más antiguo", + "Calculations.Options.latest.displayName": "Último", + "Calculations.Options.latest.label": "Último", "Calculations.Options.max.displayName": "Máx", "Calculations.Options.max.label": "Máx", "Calculations.Options.median.displayName": "Mediana", @@ -34,17 +63,54 @@ "Calculations.Options.none.displayName": "Calcular", "Calculations.Options.none.label": "Ninguna", "Calculations.Options.percentChecked.displayName": "Marcado", + "Calculations.Options.percentChecked.label": "Porcentaje marcado", + "Calculations.Options.percentUnchecked.displayName": "Desmarcado", + "Calculations.Options.percentUnchecked.label": "Porcentaje desmarcado", "Calculations.Options.range.displayName": "Rango", + "Calculations.Options.range.label": "Rango", + "Calculations.Options.sum.displayName": "Suma", + "Calculations.Options.sum.label": "Suma", + "CalendarCard.untitled": "Sin título", + "CardActionsMenu.copiedLink": "¡Copiado!", + "CardActionsMenu.copyLink": "Copiar hipervínculo", + "CardActionsMenu.delete": "Eliminar", + "CardActionsMenu.duplicate": "Duplicar", + "CardBadges.title-checkboxes": "Casillas de verificación", + "CardBadges.title-comments": "Comentarios", + "CardBadges.title-description": "Esta tarjeta tiene una descripción", + "CardDetail.Attach": "Adjuntar", + "CardDetail.Follow": "Seguir", + "CardDetail.Following": "Siguiendo", "CardDetail.add-content": "Añadir contenido", "CardDetail.add-icon": "Añadir icono", "CardDetail.add-property": "+ Añadir propiedad", - "CardDetail.addCardText": "añade texto a la tarjeta", - "CardDetail.moveContent": "mover contenido de la tarjeta", + "CardDetail.addCardText": "agregar texto a la tarjeta", + "CardDetail.limited-body": "Mejorar a nuestro plan Professional o Enterprise.", + "CardDetail.limited-button": "Mejorar", + "CardDetail.limited-title": "Esta tarjeta está oculta", + "CardDetail.moveContent": "Mover contenido de la tarjeta", "CardDetail.new-comment-placeholder": "Añadir un comentario...", - "CardDetailProperty.confirm-delete-subtext": "¿Estas seguro de que quieres eliminar la propiedad \"{nombre de la propiedad}\"? Al eliminarla se borrará la propiedad de todas las tarjetas de este tablero.", - "CardDetailProperty.property-deleted": "¡{nombre de la propiedad} ha sido eliminado exitosamente!", + "CardDetailProperty.confirm-delete-heading": "Confirmar eliminación de la propiedad", + "CardDetailProperty.confirm-delete-subtext": "¿Estás seguro de que quieres eliminar la propiedad \"{propertyName}\"? Al eliminarla también se removerá la propiedad en todas las tarjetas de este tablero.", + "CardDetailProperty.confirm-property-name-change-subtext": "¿Estás seguro de que quieres cambiar la propiedad \"{propertyName}\" {customText}? Esto puede afectar a los valores en {numOfCards} tarjeta(s) en este tablero, lo que puede resultar en una pérdida de datos.", + "CardDetailProperty.confirm-property-type-change": "Confirmar cambio de tipo de la propiedad", + "CardDetailProperty.delete-action-button": "Eliminar", + "CardDetailProperty.property-change-action-button": "Modificar propiedad", + "CardDetailProperty.property-changed": "¡Propiedad modificada exitosamente!", + "CardDetailProperty.property-deleted": "¡La propiedad {propertyName} ha sido eliminada exitosamente!", + "CardDetial.limited-link": "Aprende más sobre nuestros planes.", + "CardDialog.delete-confirmation-dialog-attachment": "Confirmar eliminación del archivo adjunto", + "CardDialog.delete-confirmation-dialog-button-text": "Eliminar", + "CardDialog.delete-confirmation-dialog-heading": "Confirmar eliminación de la tarjeta", "CardDialog.editing-template": "Estás editando una plantilla.", "CardDialog.nocard": "Esta tarjeta no existe o es inaccesible.", + "Categories.CreateCategoryDialog.CancelText": "Cancelar", + "Categories.CreateCategoryDialog.CreateText": "Crear", + "Categories.CreateCategoryDialog.Placeholder": "Pon nombre a la categoría", + "Categories.CreateCategoryDialog.UpdateText": "Actualizar", + "CenterPanel.Login": "Ingresar", + "CenterPanel.Share": "Compartir", + "ChannelIntro.CreateBoard": "Crear un tablero", "ColorOption.selectColor": "Seleccionar {color} Color", "Comment.delete": "Borrar", "CommentsList.send": "Enviar", From 0aa09a21438e66015add7719d96e4a06cc8f3c05 Mon Sep 17 00:00:00 2001 From: Moataz Muhammad Date: Mon, 27 Feb 2023 16:23:59 +0100 Subject: [PATCH 010/102] Translated using Weblate (Arabic) Currently translated at 46.0% (207 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/ar/ --- webapp/i18n/ar.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/webapp/i18n/ar.json b/webapp/i18n/ar.json index 55a58f534..8eeca566e 100644 --- a/webapp/i18n/ar.json +++ b/webapp/i18n/ar.json @@ -1,5 +1,15 @@ { "AppBar.Tooltip": "اخيار الالواح المرتبطة", + "Attachment.Attachment-title": "المرفق", + "AttachmentBlock.DeleteAction": "حذف", + "AttachmentBlock.addElement": "اضافة {type}", + "AttachmentBlock.delete": "تم حذف المرفق.", + "AttachmentBlock.failed": "تعذر تحميل هذا الملف حيث تم الوصول إلى الحد الأقصى لحجم الملفات.", + "AttachmentBlock.upload": "يتم الآن تحميل المرفق.", + "AttachmentBlock.uploadSuccess": "تم تحميل المرفق.", + "AttachmentElement.delete-confirmation-dialog-button-text": "حذف", + "AttachmentElement.download": "تحميل", + "AttachmentElement.upload-percentage": "جاري التحمي... ({uploadPercent}%)", "BoardComponent.add-a-group": "+ إضافة مجموعة", "BoardComponent.delete": "حذف", "BoardComponent.hidden-columns": "الأعمدة المخفية", @@ -155,9 +165,15 @@ "FindBoardsDialog.NoResultsFor": "لا يوجد نتيجة للبحث \"{searchQuery}\"", "FindBoardsDialog.NoResultsSubtext": "اختر بحث آخر أو تأكد من الأخطاء الإملائية.", "FindBoardsDialog.Title": "البحث عن ألواح", + "GroupBy.ungroup": "إلغاء التجميع", + "KanbanCard.untitled": "بدون عنوان", + "Mutator.new-card-from-template": "بطاقة جديدة من نموذج", + "Mutator.new-template-from-card": "نموذج جديد من بطاقة", "OnboardingTour.AddComments.Title": "إضافة تعليقات", "OnboardingTour.AddDescription.Title": "اضافة وصف", "OnboardingTour.AddProperties.Title": "إضافة خواص", + "OnboardingTour.AddView.Body": "انتقل هنا لإنشاء عرض جديد لتنظيم لوحتك باستخدام تخطيطات مختلفة.", + "OnboardingTour.AddView.Title": "إضافة عرض جديد", "OnboardingTour.CopyLink.Title": "نسخ الرابط", "PropertyMenu.Delete": "حذف", "PropertyMenu.changeType": "تغيير نوع الخاصية", From c341385c470ddd3aff7cd828d89246867e1b5c22 Mon Sep 17 00:00:00 2001 From: 11sma <11isma@gmail.com> Date: Mon, 27 Feb 2023 16:23:59 +0100 Subject: [PATCH 011/102] Translated using Weblate (Catalan) Currently translated at 43.3% (195 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/ca/ --- webapp/i18n/ca.json | 78 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 7 deletions(-) diff --git a/webapp/i18n/ca.json b/webapp/i18n/ca.json index 6e94e02cf..b6386314c 100644 --- a/webapp/i18n/ca.json +++ b/webapp/i18n/ca.json @@ -1,17 +1,81 @@ { + "Attachment.Attachment-title": "Adjunt", + "AttachmentBlock.DeleteAction": "esborra", + "AttachmentBlock.addElement": "afegir {type}", + "AttachmentBlock.delete": "Adjunt esborrat.", + "AttachmentBlock.failed": "Aquest fitxer no pot ser afegit ja que el límit de tamany de fitxer ha estat assolit.", + "AttachmentBlock.upload": "Adjunt afegint-se.", + "AttachmentBlock.uploadSuccess": "Adjunt afegit.", + "AttachmentElement.delete-confirmation-dialog-button-text": "Esborra", + "AttachmentElement.download": "Descarrega", + "AttachmentElement.upload-percentage": "Afegint...({uploadPercent}%)", "BoardComponent.add-a-group": "+ Afegir un grup", "BoardComponent.delete": "Eliminar", "BoardComponent.hidden-columns": "Columnes ocultes", "BoardComponent.hide": "Amagar", "BoardComponent.new": "+ Nou", "BoardComponent.no-property": "Sense {property}", - "BoardComponent.no-property-title": "Els elements amb una propietat {property} buida anirán aquí. Aquesta col·lumna no pot elimiar-se.", + "BoardComponent.no-property-title": "Els elements amb una propietat {property} buida anirán aquí. Aquesta col·lumna no pot eliminar-se.", "BoardComponent.show": "Mostrar", + "BoardMember.schemeAdmin": "Admin", + "BoardMember.schemeCommenter": "Comentarista", + "BoardMember.schemeEditor": "Editor", + "BoardMember.schemeNone": "Cap", + "BoardMember.schemeViewer": "Visualitzador", + "BoardPage.newVersion": "Una nova versió de Boards és disponible, clica aquí per recarregar.", + "BoardPage.syncFailed": "El tauler podria ser eliminat o revocat l'accés.", + "BoardTemplateSelector.add-template": "Crea una nova plantilla", + "BoardTemplateSelector.create-empty-board": "Crea un taulell buit", + "BoardTemplateSelector.delete-template": "Esborra", + "BoardTemplateSelector.description": "Afegeix el taulell a la barra lateral usant alguna de les plantilles definides a sota o comença des de zero.", + "BoardTemplateSelector.edit-template": "Edita", + "BoardTemplateSelector.plugin.no-content-description": "Afegeix el taulell a la barra lateral usant alguna de les plantilles definides a sota o comença des de zero.", + "BoardTemplateSelector.plugin.no-content-title": "Crea un taulell", + "BoardTemplateSelector.title": "Crea un taulell", + "BoardTemplateSelector.use-this-template": "Utilitza aquesta plantilla", + "BoardsSwitcher.Title": "Busca taulells", + "BoardsUnfurl.Updated": "Actualitzat {time}", + "Calculations.Options.average.displayName": "Promig", + "Calculations.Options.average.label": "Promig", + "Calculations.Options.countChecked.displayName": "Comprovat", + "Calculations.Options.countUniqueValue.displayName": "Únic", + "Calculations.Options.countUniqueValue.label": "Compta valors únics", + "Calculations.Options.countValue.displayName": "Valors", + "Calculations.Options.dateRange.displayName": "Rang", + "Calculations.Options.dateRange.label": "Rang", + "Calculations.Options.earliest.displayName": "Proper", + "Calculations.Options.earliest.label": "Proper", + "Calculations.Options.latest.displayName": "Últim", + "Calculations.Options.latest.label": "Últim", + "Calculations.Options.max.displayName": "Màxim", + "Calculations.Options.max.label": "Màxim", + "Calculations.Options.min.displayName": "Mínim", + "Calculations.Options.min.label": "Mínim", + "Calculations.Options.none.displayName": "Calcula", + "Calculations.Options.none.label": "Cap", + "Calculations.Options.percentChecked.displayName": "Completat", + "Calculations.Options.percentChecked.label": "Percentatge completat", + "Calculations.Options.percentUnchecked.displayName": "No finalitzat", + "Calculations.Options.percentUnchecked.label": "Percentatge no finalitzat", + "Calculations.Options.range.displayName": "Rang", + "Calculations.Options.range.label": "Rang", + "Calculations.Options.sum.displayName": "Suma", + "Calculations.Options.sum.label": "Suma", + "CalendarCard.untitled": "Sense títol", + "CardActionsMenu.copiedLink": "Copiat!", + "CardActionsMenu.copyLink": "Còpia l'enllaç", + "CardActionsMenu.delete": "Esborra", + "CardActionsMenu.duplicate": "Duplica", + "CardBadges.title-comments": "Comentaris", + "CardBadges.title-description": "Aquesta tarjeta té una descripció", + "CardDetail.Attach": "Adjunta", + "CardDetail.Follow": "Segueix", + "CardDetail.Following": "Segueix", "CardDetail.add-content": "Afegeix contingut", "CardDetail.add-icon": "Afegeix icona", "CardDetail.add-property": "+ Afegeix propietat", "CardDetail.addCardText": "afegeix text a la targeta", - "CardDetail.moveContent": "mou el contingut de la targeta", + "CardDetail.moveContent": "Mou el contingut de la targeta", "CardDetail.new-comment-placeholder": "Afegeix un comentari...", "CardDialog.editing-template": "Estas editant una plantilla.", "CardDialog.nocard": "Aquesta targeta no existeix o és innaccesible.", @@ -47,18 +111,18 @@ "PropertyMenu.changeType": "Canviar el tipus de propietat", "PropertyMenu.typeTitle": "Tipus", "PropertyType.Checkbox": "casella de verificació", - "PropertyType.CreatedBy": "Creat Per", + "PropertyType.CreatedBy": "Creada per", "PropertyType.CreatedTime": "Moment de creació", "PropertyType.Date": "Data", "PropertyType.Email": "Correu electrònic", - "PropertyType.MultiSelect": "Multi selecció", + "PropertyType.MultiSelect": "Selecció múltiple", "PropertyType.Number": "Número", "PropertyType.Person": "Persona", "PropertyType.Phone": "Telèfon", "PropertyType.Select": "Selecciona", "PropertyType.Text": "Text", - "PropertyType.UpdatedBy": "Actualitzat per", - "PropertyType.UpdatedTime": "Moment de actualització", + "PropertyType.UpdatedBy": "Última actualització feta per", + "PropertyType.UpdatedTime": "Moment d'actualització", "RegistrationLink.confirmRegenerateToken": "Això invalidarà enllaços compartits anteriorment. Continuar?", "RegistrationLink.copiedLink": "Copiat!", "RegistrationLink.copyLink": "Copiar enllaç", @@ -113,7 +177,7 @@ "ViewHeader.group-by": "Agrupar per: {property}", "ViewHeader.new": "Nou", "ViewHeader.properties": "Propietats", - "ViewHeader.search-text": "Cercar text", + "ViewHeader.search-text": "Cerca tarjetes", "ViewHeader.select-a-template": "Selecciona una plantilla", "ViewHeader.sort": "Ordenar", "ViewHeader.untitled": "Sense títol", From b553a6f21641dc3ba9d7f38512ec51e4cd3cf391 Mon Sep 17 00:00:00 2001 From: Filip Antala Date: Mon, 27 Feb 2023 16:23:59 +0100 Subject: [PATCH 012/102] Translated using Weblate (Slovak) Currently translated at 61.5% (277 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/sk/ --- webapp/i18n/sk.json | 166 ++++++++++++++++++++++++++++++++------------ 1 file changed, 123 insertions(+), 43 deletions(-) diff --git a/webapp/i18n/sk.json b/webapp/i18n/sk.json index eff2c85eb..7d5945f89 100644 --- a/webapp/i18n/sk.json +++ b/webapp/i18n/sk.json @@ -1,14 +1,40 @@ { + "Attachment.Attachment-title": "Príloha", + "AttachmentBlock.DeleteAction": "odstrániť", + "AttachmentBlock.delete": "Príloha odstránená.", + "AttachmentBlock.failed": "Tento súbor nebol nahratý, pretože presiahol veľkostný limit.", + "AttachmentBlock.upload": "Príloha sa nahráva.", + "AttachmentBlock.uploadSuccess": "Príloha bola nahratá.", + "AttachmentElement.delete-confirmation-dialog-button-text": "Odstrániť", + "AttachmentElement.download": "Stiahnuť", + "AttachmentElement.upload-percentage": "Nahrávam... ({uploadPercent}%)", "BoardComponent.add-a-group": "+ Pridaj skupinu", - "BoardComponent.delete": "Mazať", - "BoardComponent.hidden-columns": "Skryté stľpce", + "BoardComponent.delete": "Odstrániť", + "BoardComponent.hidden-columns": "Skryté stĺpce", "BoardComponent.hide": "Skryť", "BoardComponent.new": "+ Nový", "BoardComponent.no-property": "žiadna {property}", "BoardComponent.no-property-title": "Položky s prázdnou {property} pôjdu tu. Tento stĺpec nemožno vymazať.", "BoardComponent.show": "Ukáž", + "BoardMember.schemeAdmin": "Administrátor", + "BoardMember.schemeCommenter": "Komentátor", + "BoardMember.schemeEditor": "Editor", + "BoardMember.schemeNone": "Žiadny", + "BoardMember.schemeViewer": "Sledovateľ", + "BoardMember.unlinkChannel": "Odpojiť", "BoardPage.newVersion": "Nová verzia je dostupná, kliknite tu pre znovu načítanie.", - "BoardPage.syncFailed": "Nástenka môže byť vymazaná, alebo prístup odobraný.", + "BoardPage.syncFailed": "Nástenka môže byť vymazaná alebo prístup odobraný.", + "BoardTemplateSelector.add-template": "Vytvoriť novú šablónu", + "BoardTemplateSelector.create-empty-board": "Vytvoriť prázdnu nástenku", + "BoardTemplateSelector.delete-template": "Odstrániť", + "BoardTemplateSelector.description": "Pridajte nástenku do bočného panelu pomocou ktorýchkoľvek šablón definovaných dole alebo začnite od začiatku.", + "BoardTemplateSelector.edit-template": "Upraviť", + "BoardTemplateSelector.plugin.no-content-description": "Pridajte nástenku do bočného panelu pomocou ktorýchkoľvek šablón dole alebo začnite od začiatku.", + "BoardTemplateSelector.plugin.no-content-title": "Vytvoriť nástenku", + "BoardTemplateSelector.title": "Vytvoriť nástenku", + "BoardTemplateSelector.use-this-template": "Použiť túto šablónu", + "BoardsSwitcher.Title": "Hľadať nástenky", + "BoardsUnfurl.Limited": "Ďalšie detaily sú skryté, pretože je karta archivovaná", "BoardsUnfurl.Remainder": "+{remainder} viac", "BoardsUnfurl.Updated": "Upravené {time}", "Calculations.Options.average.displayName": "Priemer", @@ -16,13 +42,13 @@ "Calculations.Options.count.displayName": "Počet", "Calculations.Options.count.label": "Počet", "Calculations.Options.countChecked.displayName": "Označené", - "Calculations.Options.countChecked.label": "Spočítaj označené", + "Calculations.Options.countChecked.label": "Počítať označené", "Calculations.Options.countUnchecked.displayName": "Neoznačené", - "Calculations.Options.countUnchecked.label": "Spočítaj neoznačené", + "Calculations.Options.countUnchecked.label": "Počítať neoznačené", "Calculations.Options.countUniqueValue.displayName": "Unikátne", - "Calculations.Options.countUniqueValue.label": "Spočítaj unikátne hodnoty", + "Calculations.Options.countUniqueValue.label": "Počítať unikátne hodnoty", "Calculations.Options.countValue.displayName": "Hodnoty", - "Calculations.Options.countValue.label": "Spočítaj hodnoty", + "Calculations.Options.countValue.label": "Počítať hodnotu", "Calculations.Options.dateRange.displayName": "Rozsah", "Calculations.Options.dateRange.label": "Rozsah", "Calculations.Options.earliest.displayName": "Prvý", @@ -31,76 +57,130 @@ "Calculations.Options.latest.label": "Posledný", "Calculations.Options.max.displayName": "Max", "Calculations.Options.max.label": "Max", - "Calculations.Options.median.displayName": "Median", - "Calculations.Options.median.label": "Median", + "Calculations.Options.median.displayName": "Medián", + "Calculations.Options.median.label": "Medián", "Calculations.Options.min.displayName": "Min", "Calculations.Options.min.label": "Min", - "Calculations.Options.none.displayName": "Vypočítaj", + "Calculations.Options.none.displayName": "Vypočítať", "Calculations.Options.none.label": "Nič", - "Calculations.Options.percentChecked.displayName": "Skontrolované", - "Calculations.Options.percentChecked.label": "Percent Skontrolovaných", + "Calculations.Options.percentChecked.displayName": "Označené", + "Calculations.Options.percentChecked.label": "Percent skontrolovaných", "Calculations.Options.percentUnchecked.displayName": "Neskontrolované", "Calculations.Options.percentUnchecked.label": "Percent neskontrolovaných", "Calculations.Options.range.displayName": "Rozsah", "Calculations.Options.range.label": "Rozsah", "Calculations.Options.sum.displayName": "Súčet", "Calculations.Options.sum.label": "Súčet", - "CardDetail.Follow": "Sleduj", - "CardDetail.Following": "Sledujúce", - "CardDetail.add-content": "Pridaj obsah", - "CardDetail.add-icon": "Pridaj ikonu", - "CardDetail.add-property": "+ Pridaj vlastnosť", - "CardDetail.addCardText": "Pridaj text karty", - "CardDetail.moveContent": "presuň obsah karty", - "CardDetail.new-comment-placeholder": "Pridaj komentár ...", - "CardDetailProperty.confirm-delete-heading": "Potvrď vymazanie vlastnosti", - "CardDetailProperty.confirm-delete-subtext": "Skutočne chcete vymazať \"{propertyName}\"? Mazaním ju odstránite zo všetkých kariet na tabuli.", - "CardDetailProperty.confirm-property-name-change-subtext": "Skutočne chcete vymazať \"{propertyName}\" {customText}? Ovplyvní to hodnoty na {numOfCards} kartách na tabuli, a môže viesť k strate dát.", - "CardDetailProperty.confirm-property-type-change": "Potvrď zmenu typu vlastnosti!", + "CalendarCard.untitled": "Bez názvu", + "CardActionsMenu.copiedLink": "Skopírované!", + "CardActionsMenu.copyLink": "Skopírovať odkaz", + "CardActionsMenu.delete": "Odstrániť", + "CardActionsMenu.duplicate": "Duplikovať", + "CardBadges.title-checkboxes": "Začiarkávacie políčka", + "CardBadges.title-comments": "Komentáre", + "CardBadges.title-description": "Táto karta má popis", + "CardDetail.Attach": "Priložiť", + "CardDetail.Follow": "Sledovať", + "CardDetail.Following": "Sledujúci", + "CardDetail.add-content": "Pridať obsah", + "CardDetail.add-icon": "Pridať ikonu", + "CardDetail.add-property": "+ Pridať vlastnosť", + "CardDetail.addCardText": "pridať text karty", + "CardDetail.limited-body": "Vylepšiť na náš Professional alebo Enterprise plán.", + "CardDetail.limited-button": "Zmeniť plán", + "CardDetail.limited-title": "Táto karta je skrytá", + "CardDetail.moveContent": "Presunúť obsah karty", + "CardDetail.new-comment-placeholder": "Pridať komentár...", + "CardDetailProperty.confirm-delete-heading": "Potvrdiť vymazanie vlastnosti", + "CardDetailProperty.confirm-delete-subtext": "Skutočne chcete vymazať hodnotu \"{propertyName}\"? Bude odstránená zo všetkých kariet na tejto tabuli.", + "CardDetailProperty.confirm-property-name-change-subtext": "Skutočne chcete zmeniť hodnotu \"{propertyName}\" {customText}? Ovplyvní to {numOfCards} kariet na tabuli a môže viesť k strate dát.", + "CardDetailProperty.confirm-property-type-change": "Potvrdiť zmenu typu vlastnosti", "CardDetailProperty.delete-action-button": "Odstrániť", "CardDetailProperty.property-change-action-button": "Zmeniť vlastnosť", "CardDetailProperty.property-changed": "Zmena vlastnosti úspešná!", - "CardDetailProperty.property-deleted": "Mazanie {propertyName} úspešné!", - "CardDetailProperty.property-name-change-subtext": "typ od \"{oldPropType}\" do \"{newPropType}\"", - "CardDialog.editing-template": "Editujete template.", - "CardDialog.nocard": "Karta neexistuje alebo je neprístupná.", - "ColorOption.selectColor": "Vyber {color} farbu", + "CardDetailProperty.property-deleted": "Odstránenie {propertyName} úspešné!", + "CardDetailProperty.property-name-change-subtext": "typ z \"{oldPropType}\" na \"{newPropType}\"", + "CardDetial.limited-link": "Dozvedieť sa viac o našich plánoch.", + "CardDialog.delete-confirmation-dialog-attachment": "Potvrdiť odstránenie prílohy", + "CardDialog.delete-confirmation-dialog-button-text": "Odstrániť", + "CardDialog.delete-confirmation-dialog-heading": "Potvrdiť odstránenie karty", + "CardDialog.editing-template": "Upravujete šablónu.", + "CardDialog.nocard": "Táto karta neexistuje alebo nie je prístupná.", + "Categories.CreateCategoryDialog.CancelText": "Zrušiť", + "Categories.CreateCategoryDialog.CreateText": "Vytvoriť", + "Categories.CreateCategoryDialog.Placeholder": "Nazvite Vašu kategóriu", + "Categories.CreateCategoryDialog.UpdateText": "Zmeniť", + "CenterPanel.Login": "Prihlásiť sa", + "CenterPanel.Share": "Zdieľať", + "ChannelIntro.CreateBoard": "Vytvoriť nástenku", + "CloudMessage.cloud-server": "Získajte vlastný cloudový server zadarmo.", + "ColorOption.selectColor": "Vyberte {color} farbu", "Comment.delete": "Odstrániť", - "CommentsList.send": "Poslať", + "CommentsList.send": "Odoslať", + "ConfirmPerson.empty": "Prázdne", + "ConfirmPerson.search": "Vyhľadať...", "ConfirmationDialog.cancel-action": "Zrušiť", "ConfirmationDialog.confirm-action": "Potvrdiť", "ContentBlock.Delete": "Odstrániť", - "ContentBlock.DeleteAction": "Odstrániť", - "ContentBlock.addElement": "pridaj {type}", - "ContentBlock.checkbox": "checkbox", + "ContentBlock.DeleteAction": "odstrániť", + "ContentBlock.addElement": "pridať {type}", + "ContentBlock.checkbox": "začiarkávacie pole", "ContentBlock.divider": "oddeľovač", - "ContentBlock.editCardCheckbox": "označený-checkbox", + "ContentBlock.editCardCheckbox": "Začiarknuté pole", "ContentBlock.editCardCheckboxText": "upraviť text karty", "ContentBlock.editCardText": "upraviť text karty", "ContentBlock.editText": "Upraviť text...", "ContentBlock.image": "obrázok", - "ContentBlock.insertAbove": "vlož nad", - "ContentBlock.moveDown": "Presuň dole", - "ContentBlock.moveUp": "Presuň hore", + "ContentBlock.insertAbove": "Vložiť nad", + "ContentBlock.moveBlock": "presunúť obsah karty", + "ContentBlock.moveDown": "Presunúť dole", + "ContentBlock.moveUp": "Presunúť hore", "ContentBlock.text": "text", + "DateRange.clear": "Vyčistiť", + "DateRange.empty": "Prázdny", + "DateRange.endDate": "Koncový dátum", + "DateRange.today": "Dnes", "DeleteBoardDialog.confirm-cancel": "Zrušiť", "DeleteBoardDialog.confirm-delete": "Odstrániť", "DeleteBoardDialog.confirm-info": "Naozaj chcete odstrániť nástenku “{boardTitle}”? Odstránením vymažete všetky karty na tabuli.", + "DeleteBoardDialog.confirm-info-template": "Naozaj chcete odstrániť nástenkovú šablónu \"{boardTitle}\"?", "DeleteBoardDialog.confirm-tite": "Potvrďte odstránenie nástenky", - "Dialog.closeDialog": "Zavrieť dialog", + "DeleteBoardDialog.confirm-tite-template": "Potvrdiť odstránenie šablóny nástenky", + "Dialog.closeDialog": "Zatvoriť dialógové okno", "EditableDayPicker.today": "Dnes", - "Error.mobileweb": "Mobile web support is currently in early beta. Not all functionality may be present.", - "Error.websocket-closed": "Websocket pripojenie zlyhalo - prerušené. Skontrolujte konfiguráciu servera ak problém pretrváva.", + "Error.mobileweb": "Podpora pre mobilné prehliadače je v skorej bete. Niektoré funkcionality môžu chýbať.", + "Error.websocket-closed": "Websocket pripojenie zlyhalo - bolo prerušené. Pokiaľ problém pretrváva, skontrolujte konfiguráciu servera.", + "Filter.contains": "obsahuje", + "Filter.ends-with": "končí s", "Filter.includes": "zahŕňa", + "Filter.is": "je", "Filter.is-empty": "je prázdny", "Filter.is-not-empty": "nie je prázdny", + "Filter.is-not-set": "nie je nastavený", + "Filter.is-set": "je nastavený", + "Filter.not-contains": "neobsahuje", + "Filter.not-ends-with": "nekončí s", "Filter.not-includes": "nezahŕňa", + "Filter.not-starts-with": "nezačína s", + "Filter.starts-with": "začína s", + "FilterByText.placeholder": "text filtra", "FilterComponent.add-filter": "+ Pridaj filter", "FilterComponent.delete": "Odstrániť", + "FilterValue.empty": "(prázdny)", + "FindBoardsDialog.IntroText": "Vyhľadať nástenky", + "FindBoardsDialog.NoResultsFor": "Žiadne výsledky pre \"{searchQuery}\"", + "FindBoardsDialog.NoResultsSubtext": "Skontrolujte pravopis alebo vyskúšajte iný pojem.", + "FindBoardsDialog.SubTitle": "Nájdite nástenku písaním. Použite HORE/DOLE na prehliadanie, ENTER na vybratie a ESC na zrušenie", + "FindBoardsDialog.Title": "Nájsť nástenky", + "GroupBy.hideEmptyGroups": "Skryť {count} prázdnych skupín", + "GroupBy.showHiddenGroups": "Zobraziť {count} prázdnych skupín", "GroupBy.ungroup": "Zrušiť zoskupenie", - "KanbanCard.untitled": "Nepomenované", - "Mutator.new-card-from-template": "nová karta z template-u", - "Mutator.new-template-from-card": "nový template z karty", + "HideBoard.MenuOption": "Skryť nástenku", + "KanbanCard.untitled": "Bez názvu", + "MentionSuggestion.is-not-board-member": "(nie je členom nástenky)", + "Mutator.new-board-from-template": "nová nástenka zo šablóny", + "Mutator.new-card-from-template": "nová karta zo šablóny", + "Mutator.new-template-from-card": "nová šablóna z karty", "PropertyMenu.Delete": "Odstrániť", "PropertyMenu.changeType": "Zmeniť vlastnosť", "PropertyMenu.selectType": "Vybrať vlastnosť", From bd7608ff11aa63d16fd391ba680aa9eb3066b786 Mon Sep 17 00:00:00 2001 From: hattori611 Date: Mon, 27 Feb 2023 16:24:00 +0100 Subject: [PATCH 013/102] Translated using Weblate (Vietnamese) Currently translated at 6.6% (30 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/vi/ --- webapp/i18n/vi.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/webapp/i18n/vi.json b/webapp/i18n/vi.json index 921d2f784..aec863456 100644 --- a/webapp/i18n/vi.json +++ b/webapp/i18n/vi.json @@ -1,4 +1,7 @@ { + "AppBar.Tooltip": "Chuyển sang các bảng đã liên kết", + "Attachment.Attachment-title": "Đính kèm", + "AttachmentBlock.DeleteAction": "xóa", "BoardComponent.add-a-group": "+ Thêm nhóm", "BoardComponent.delete": "Xóa", "BoardComponent.hidden-columns": "Cột ẩn", From 805e0d93dc30c5decbb5419ad766e3982affaaec Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Thu, 2 Mar 2023 04:09:32 -0700 Subject: [PATCH 014/102] disable patches on read-only unmount (#4608) --- webapp/src/properties/url/url.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/webapp/src/properties/url/url.tsx b/webapp/src/properties/url/url.tsx index 047fe3490..5280ead1b 100644 --- a/webapp/src/properties/url/url.tsx +++ b/webapp/src/properties/url/url.tsx @@ -35,11 +35,14 @@ const URLProperty = (props: PropertyProps): JSX.Element => { if (value !== (props.card.fields.properties[props.propertyTemplate?.id || ''] || '')) { mutator.changePropertyValue(props.board.id, props.card, props.propertyTemplate?.id || '', value) } - }, [props.card, props.propertyTemplate, value]) + }, [props.board.id, props.card, props.propertyTemplate?.id, value]) const saveTextPropertyRef = useRef<() => void>(saveTextProperty) - saveTextPropertyRef.current = saveTextProperty - + if (props.readOnly) { + saveTextPropertyRef.current = () => null + } else { + saveTextPropertyRef.current = saveTextProperty + } useEffect(() => { return () => { saveTextPropertyRef.current && saveTextPropertyRef.current() From c01776e92a59317dc122bee4d03a18958def5580 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Thu, 2 Mar 2023 16:35:51 -0700 Subject: [PATCH 015/102] update version to v7.10.0 --- mattermost-plugin/plugin.json | 2 +- mattermost-plugin/server/manifest.go | 2 +- server/model/version.go | 1 + webapp/package-lock.json | 4 ++-- webapp/package.json | 2 +- .../__snapshots__/globalHeader.test.tsx.snap | 2 +- .../__snapshots__/sidebar.test.tsx.snap | 20 +++++++++---------- webapp/src/constants.ts | 4 ++-- 8 files changed, 19 insertions(+), 18 deletions(-) diff --git a/mattermost-plugin/plugin.json b/mattermost-plugin/plugin.json index 7c458cc74..a02f513bc 100644 --- a/mattermost-plugin/plugin.json +++ b/mattermost-plugin/plugin.json @@ -6,7 +6,7 @@ "support_url": "https://github.com/mattermost/focalboard/issues", "release_notes_url": "https://github.com/mattermost/focalboard/releases", "icon_path": "assets/starter-template-icon.svg", - "version": "7.9.0", + "version": "7.10.0", "min_server_version": "7.2.0", "server": { "executables": { diff --git a/mattermost-plugin/server/manifest.go b/mattermost-plugin/server/manifest.go index db79def9f..d950ee0ca 100644 --- a/mattermost-plugin/server/manifest.go +++ b/mattermost-plugin/server/manifest.go @@ -20,7 +20,7 @@ const manifestStr = ` "support_url": "https://github.com/mattermost/focalboard/issues", "release_notes_url": "https://github.com/mattermost/focalboard/releases", "icon_path": "assets/starter-template-icon.svg", - "version": "7.9.0", + "version": "7.10.0", "min_server_version": "7.2.0", "server": { "executables": { diff --git a/server/model/version.go b/server/model/version.go index cace1f357..52fe08e79 100644 --- a/server/model/version.go +++ b/server/model/version.go @@ -8,6 +8,7 @@ import ( // It should be maintained in chronological order with most current // release at the front of the list. var versions = []string{ + "7.10.0", "7.9.0", "7.8.0", "7.7.0", diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 65f21b94b..9de98ccbd 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -1,12 +1,12 @@ { "name": "focalboard", - "version": "7.9.0", + "version": "7.10.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "focalboard", - "version": "7.9.0", + "version": "7.10.0", "dependencies": { "@draft-js-plugins/editor": "^4.1.2", "@draft-js-plugins/emoji": "^4.6.0", diff --git a/webapp/package.json b/webapp/package.json index d26d1e3ae..935c76e31 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -1,6 +1,6 @@ { "name": "focalboard", - "version": "7.9.0", + "version": "7.10.0", "private": true, "description": "", "scripts": { diff --git a/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap b/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap index a348d7b30..ffd6d4819 100644 --- a/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap +++ b/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap @@ -10,7 +10,7 @@ exports[`components/sidebar/GlobalHeader header menu should match snapshot 1`] = /> diff --git a/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap b/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap index 8fc1ab28c..4533b2b83 100644 --- a/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap +++ b/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap @@ -51,9 +51,9 @@ exports[`components/sidebarSidebar dont show hidden boards 1`] = ` >
- v7.9.0 + v7.10.0
@@ -252,9 +252,9 @@ exports[`components/sidebarSidebar should assign default category if current boa >
- v7.9.0 + v7.10.0
@@ -508,9 +508,9 @@ exports[`components/sidebarSidebar shouldnt do any category assignment is board >
- v7.9.0 + v7.10.0
@@ -919,9 +919,9 @@ exports[`components/sidebarSidebar sidebar hidden 1`] = ` >
- v7.9.0 + v7.10.0
@@ -1213,9 +1213,9 @@ exports[`components/sidebarSidebar some categories hidden 1`] = ` >
- v7.9.0 + v7.10.0
diff --git a/webapp/src/constants.ts b/webapp/src/constants.ts index d900092b1..9331eebe4 100644 --- a/webapp/src/constants.ts +++ b/webapp/src/constants.ts @@ -37,8 +37,8 @@ class Constants { static readonly titleColumnId = '__title' static readonly badgesColumnId = '__badges' - static readonly versionString = '7.9.0' - static readonly versionDisplayString = 'Mar 2023' + static readonly versionString = '7.10.0' + static readonly versionDisplayString = 'Apr 2023' static readonly archiveHelpPage = 'https://docs.mattermost.com/boards/migrate-to-boards.html' static readonly imports = [ From 39dbdbba7721ba5bd589c83c01a5fa2a620a1afb Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Fri, 3 Mar 2023 15:10:23 +0530 Subject: [PATCH 016/102] Added data migration to de-duplicate data from category_boards table --- .../store/sqlstore/data_migrations.go | 96 ++++++++++++++++++- server/services/store/sqlstore/migrate.go | 10 ++ ...ategory_board_add_unique_constraint.up.sql | 2 +- 3 files changed, 102 insertions(+), 6 deletions(-) diff --git a/server/services/store/sqlstore/data_migrations.go b/server/services/store/sqlstore/data_migrations.go index ae1974792..a505cb97d 100644 --- a/server/services/store/sqlstore/data_migrations.go +++ b/server/services/store/sqlstore/data_migrations.go @@ -21,11 +21,12 @@ const ( // query, so we want to stay safely below. CategoryInsertBatch = 1000 - TemplatesToTeamsMigrationKey = "TemplatesToTeamsMigrationComplete" - UniqueIDsMigrationKey = "UniqueIDsMigrationComplete" - CategoryUUIDIDMigrationKey = "CategoryUuidIdMigrationComplete" - TeamLessBoardsMigrationKey = "TeamLessBoardsMigrationComplete" - DeletedMembershipBoardsMigrationKey = "DeletedMembershipBoardsMigrationComplete" + TemplatesToTeamsMigrationKey = "TemplatesToTeamsMigrationComplete" + UniqueIDsMigrationKey = "UniqueIDsMigrationComplete" + CategoryUUIDIDMigrationKey = "CategoryUuidIdMigrationComplete" + TeamLessBoardsMigrationKey = "TeamLessBoardsMigrationComplete" + DeletedMembershipBoardsMigrationKey = "DeletedMembershipBoardsMigrationComplete" + DeDuplicateCategoryBoardTableMigrationKey = "DeDuplicateCategoryBoardTableComplete" ) func (s *SQLStore) getBlocksWithSameID(db sq.BaseRunner) ([]*model.Block, error) { @@ -790,3 +791,88 @@ func (s *SQLStore) getCollationAndCharset(tableName string) (string, string, err return collation, charSet, nil } + +func (s *SQLStore) RunDeDuplicateCategoryBoardsMigration(currentMigration int) error { + setting, err := s.GetSystemSetting(DeDuplicateCategoryBoardTableMigrationKey) + if err != nil { + return fmt.Errorf("cannot get DeDuplicateCategoryBoardTableMigration state: %w", err) + } + + // If the migration is already completed, do not run it again. + if hasAlreadyRun, _ := strconv.ParseBool(setting); hasAlreadyRun { + return nil + } + + if currentMigration >= (deDuplicateCategoryBoards + 1) { + // if the migration for which we're fixing the data is already applied, + // no need to check fix anything + + if err := s.setSystemSetting(s.db, DeDuplicateCategoryBoardTableMigrationKey, strconv.FormatBool(true)); err != nil { + return fmt.Errorf("cannot mark migration %s as completed: %w", "RunDeDuplicateCategoryBoardsMigration", err) + } + return nil + } + + needed, err := s.doesDuplicateCategoryBoardsExist() + if err != nil { + return err + } + + if !needed { + if err := s.setSystemSetting(s.db, DeDuplicateCategoryBoardTableMigrationKey, strconv.FormatBool(true)); err != nil { + return fmt.Errorf("cannot mark migration %s as completed: %w", "RunDeDuplicateCategoryBoardsMigration", err) + } + } + + if s.dbType == model.MysqlDBType { + return s.runMySQLDeDuplicateCategoryBoardsMigration() + } else if s.dbType == model.PostgresDBType { + return s.runPostgresDeDuplicateCategoryBoardsMigration() + } + + if err := s.setSystemSetting(s.db, DeDuplicateCategoryBoardTableMigrationKey, strconv.FormatBool(true)); err != nil { + return fmt.Errorf("cannot mark migration %s as completed: %w", "RunDeDuplicateCategoryBoardsMigration", err) + } + + return nil +} + +func (s *SQLStore) doesDuplicateCategoryBoardsExist() (bool, error) { + subQuery := s.getQueryBuilder(s.db). + Select("user_id", "board_id", "count(*) AS count"). + From(s.tablePrefix+"category_boards"). + GroupBy("user_id", "board_id"). + Having("count(*) > 1") + + query := s.getQueryBuilder(s.db). + Select("COUNT(*)"). + FromSelect(subQuery, "duplicate_dataset") + + row := query.QueryRow() + + count := 0 + if err := row.Scan(&count); err != nil { + s.logger.Error("Error occurred reading number of duplicate records in category_boards table", mlog.Err(err)) + return false, err + } + + return count > 0, nil +} + +func (s *SQLStore) runMySQLDeDuplicateCategoryBoardsMigration() error { + query := fmt.Sprintf("WITH duplicates AS (SELECT id, ROW_NUMBER() OVER(PARTITION BY user_id, board_id) AS rownum FROM %[1]scategory_boards) DELETE %[1]scategory_boards FROM %[1]scategory_boards JOIN duplicates USING(id) WHERE duplicates.rownum > 1;", s.tablePrefix) + if _, err := s.db.Exec(query); err != nil { + s.logger.Error("Failed to de-duplicate data in category_boards table", mlog.Err(err)) + } + + return nil +} + +func (s *SQLStore) runPostgresDeDuplicateCategoryBoardsMigration() error { + query := fmt.Sprintf("WITH duplicates AS (SELECT id, ROW_NUMBER() OVER(PARTITION BY user_id, board_id) AS rownum FROM %[1]scategory_boards) DELETE FROM %[1]scategory_boards USING duplicates WHERE %[1]scategory_boards.id = duplicates.id AND duplicates.rownum > 1;", s.tablePrefix) + if _, err := s.db.Exec(query); err != nil { + s.logger.Error("Failed to de-duplicate data in category_boards table", mlog.Err(err)) + } + + return nil +} diff --git a/server/services/store/sqlstore/migrate.go b/server/services/store/sqlstore/migrate.go index afd9463ac..dd1be4d5f 100644 --- a/server/services/store/sqlstore/migrate.go +++ b/server/services/store/sqlstore/migrate.go @@ -36,6 +36,7 @@ const ( uniqueIDsMigrationRequiredVersion = 14 teamLessBoardsMigrationRequiredVersion = 18 categoriesUUIDIDMigrationRequiredVersion = 20 + deDuplicateCategoryBoards = 35 tempSchemaMigrationTableName = "temp_schema_migration" ) @@ -248,6 +249,15 @@ func (s *SQLStore) runMigrationSequence(engine *morph.Morph, driver drivers.Driv return err } + if mErr := s.ensureMigrationsAppliedUpToVersion(engine, driver, deDuplicateCategoryBoards); mErr != nil { + return mErr + } + + currentMigrationVersion := len(appliedMigrations) + if mErr := s.RunDeDuplicateCategoryBoardsMigration(currentMigrationVersion); err != nil { + return mErr + } + s.logger.Debug("== Applying all remaining migrations ====================", mlog.Int("current_version", len(appliedMigrations)), ) diff --git a/server/services/store/sqlstore/migrations/000036_category_board_add_unique_constraint.up.sql b/server/services/store/sqlstore/migrations/000036_category_board_add_unique_constraint.up.sql index 8858033b0..4a658bdb3 100644 --- a/server/services/store/sqlstore/migrations/000036_category_board_add_unique_constraint.up.sql +++ b/server/services/store/sqlstore/migrations/000036_category_board_add_unique_constraint.up.sql @@ -23,4 +23,4 @@ SELECT id, user_id, category_id, board_id, create_at, update_at, sort_order, hidden FROM {{.prefix}}category_boards_old; DROP TABLE {{.prefix}}category_boards_old; -{{end}} \ No newline at end of file +{{end}} From 7195a2bf1d9e10210f0d2ae137b5e78df984a490 Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Fri, 3 Mar 2023 15:45:24 +0530 Subject: [PATCH 017/102] Lint fix --- mattermost-plugin/server/manifest.go | 3 +-- .../store/sqlstore/data_migrations.go | 22 ++++++++++++------- server/services/store/sqlstore/migrate.go | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/mattermost-plugin/server/manifest.go b/mattermost-plugin/server/manifest.go index db79def9f..941134c75 100644 --- a/mattermost-plugin/server/manifest.go +++ b/mattermost-plugin/server/manifest.go @@ -45,8 +45,7 @@ const manifestStr = ` "type": "bool", "help_text": "This allows board editors to share boards that can be accessed by anyone with the link.", "placeholder": "", - "default": false, - "hosting": "" + "default": false } ] } diff --git a/server/services/store/sqlstore/data_migrations.go b/server/services/store/sqlstore/data_migrations.go index a505cb97d..8d0a3dad3 100644 --- a/server/services/store/sqlstore/data_migrations.go +++ b/server/services/store/sqlstore/data_migrations.go @@ -807,8 +807,8 @@ func (s *SQLStore) RunDeDuplicateCategoryBoardsMigration(currentMigration int) e // if the migration for which we're fixing the data is already applied, // no need to check fix anything - if err := s.setSystemSetting(s.db, DeDuplicateCategoryBoardTableMigrationKey, strconv.FormatBool(true)); err != nil { - return fmt.Errorf("cannot mark migration %s as completed: %w", "RunDeDuplicateCategoryBoardsMigration", err) + if mErr := s.setSystemSetting(s.db, DeDuplicateCategoryBoardTableMigrationKey, strconv.FormatBool(true)); mErr != nil { + return fmt.Errorf("cannot mark migration %s as completed: %w", "RunDeDuplicateCategoryBoardsMigration", mErr) } return nil } @@ -819,8 +819,8 @@ func (s *SQLStore) RunDeDuplicateCategoryBoardsMigration(currentMigration int) e } if !needed { - if err := s.setSystemSetting(s.db, DeDuplicateCategoryBoardTableMigrationKey, strconv.FormatBool(true)); err != nil { - return fmt.Errorf("cannot mark migration %s as completed: %w", "RunDeDuplicateCategoryBoardsMigration", err) + if mErr := s.setSystemSetting(s.db, DeDuplicateCategoryBoardTableMigrationKey, strconv.FormatBool(true)); mErr != nil { + return fmt.Errorf("cannot mark migration %s as completed: %w", "RunDeDuplicateCategoryBoardsMigration", mErr) } } @@ -830,8 +830,8 @@ func (s *SQLStore) RunDeDuplicateCategoryBoardsMigration(currentMigration int) e return s.runPostgresDeDuplicateCategoryBoardsMigration() } - if err := s.setSystemSetting(s.db, DeDuplicateCategoryBoardTableMigrationKey, strconv.FormatBool(true)); err != nil { - return fmt.Errorf("cannot mark migration %s as completed: %w", "RunDeDuplicateCategoryBoardsMigration", err) + if mErr := s.setSystemSetting(s.db, DeDuplicateCategoryBoardTableMigrationKey, strconv.FormatBool(true)); mErr != nil { + return fmt.Errorf("cannot mark migration %s as completed: %w", "RunDeDuplicateCategoryBoardsMigration", mErr) } return nil @@ -860,7 +860,10 @@ func (s *SQLStore) doesDuplicateCategoryBoardsExist() (bool, error) { } func (s *SQLStore) runMySQLDeDuplicateCategoryBoardsMigration() error { - query := fmt.Sprintf("WITH duplicates AS (SELECT id, ROW_NUMBER() OVER(PARTITION BY user_id, board_id) AS rownum FROM %[1]scategory_boards) DELETE %[1]scategory_boards FROM %[1]scategory_boards JOIN duplicates USING(id) WHERE duplicates.rownum > 1;", s.tablePrefix) + query := "WITH duplicates AS (SELECT id, ROW_NUMBER() OVER(PARTITION BY user_id, board_id) AS rownum " + + "FROM " + s.tablePrefix + "category_boards) " + + "DELETE " + s.tablePrefix + "category_boards FROM " + s.tablePrefix + "category_boards " + + "JOIN duplicates USING(id) WHERE duplicates.rownum > 1;" if _, err := s.db.Exec(query); err != nil { s.logger.Error("Failed to de-duplicate data in category_boards table", mlog.Err(err)) } @@ -869,7 +872,10 @@ func (s *SQLStore) runMySQLDeDuplicateCategoryBoardsMigration() error { } func (s *SQLStore) runPostgresDeDuplicateCategoryBoardsMigration() error { - query := fmt.Sprintf("WITH duplicates AS (SELECT id, ROW_NUMBER() OVER(PARTITION BY user_id, board_id) AS rownum FROM %[1]scategory_boards) DELETE FROM %[1]scategory_boards USING duplicates WHERE %[1]scategory_boards.id = duplicates.id AND duplicates.rownum > 1;", s.tablePrefix) + query := "WITH duplicates AS (SELECT id, ROW_NUMBER() OVER(PARTITION BY user_id, board_id) AS rownum " + + "FROM " + s.tablePrefix + "category_boards) " + + "DELETE FROM " + s.tablePrefix + "category_boards USING duplicates " + + "WHERE " + s.tablePrefix + "category_boards.id = duplicates.id AND duplicates.rownum > 1;" if _, err := s.db.Exec(query); err != nil { s.logger.Error("Failed to de-duplicate data in category_boards table", mlog.Err(err)) } diff --git a/server/services/store/sqlstore/migrate.go b/server/services/store/sqlstore/migrate.go index dd1be4d5f..d3fd7e3c5 100644 --- a/server/services/store/sqlstore/migrate.go +++ b/server/services/store/sqlstore/migrate.go @@ -254,7 +254,7 @@ func (s *SQLStore) runMigrationSequence(engine *morph.Morph, driver drivers.Driv } currentMigrationVersion := len(appliedMigrations) - if mErr := s.RunDeDuplicateCategoryBoardsMigration(currentMigrationVersion); err != nil { + if mErr := s.RunDeDuplicateCategoryBoardsMigration(currentMigrationVersion); mErr != nil { return mErr } From 1e3c03354724425b4448faf1ee40fd4e702a4a25 Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Fri, 3 Mar 2023 15:55:52 +0530 Subject: [PATCH 018/102] shortcircuit for mysql --- server/services/store/sqlstore/data_migrations.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/server/services/store/sqlstore/data_migrations.go b/server/services/store/sqlstore/data_migrations.go index 8d0a3dad3..15d86129d 100644 --- a/server/services/store/sqlstore/data_migrations.go +++ b/server/services/store/sqlstore/data_migrations.go @@ -793,6 +793,14 @@ func (s *SQLStore) getCollationAndCharset(tableName string) (string, string, err } func (s *SQLStore) RunDeDuplicateCategoryBoardsMigration(currentMigration int) error { + // not supported for SQLite + if s.dbType == model.SqliteDBType { + if mErr := s.setSystemSetting(s.db, DeDuplicateCategoryBoardTableMigrationKey, strconv.FormatBool(true)); mErr != nil { + return fmt.Errorf("cannot mark migration %s as completed: %w", "RunDeDuplicateCategoryBoardsMigration", mErr) + } + return nil + } + setting, err := s.GetSystemSetting(DeDuplicateCategoryBoardTableMigrationKey) if err != nil { return fmt.Errorf("cannot get DeDuplicateCategoryBoardTableMigration state: %w", err) From f9aa6c1668a7f3dd91c89e2f720a5c9958cb312a Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Fri, 3 Mar 2023 18:49:53 +0530 Subject: [PATCH 019/102] Fixed server test --- server/services/store/storetests/system.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/services/store/storetests/system.go b/server/services/store/storetests/system.go index d6fa83a99..6a59826aa 100644 --- a/server/services/store/storetests/system.go +++ b/server/services/store/storetests/system.go @@ -10,8 +10,9 @@ import ( // these system settings are created when running the data migrations, // so they will be present after the tests setup. var dataMigrationSystemSettings = map[string]string{ - "UniqueIDsMigrationComplete": "true", - "CategoryUuidIdMigrationComplete": "true", + "UniqueIDsMigrationComplete": "true", + "CategoryUuidIdMigrationComplete": "true", + "DeDuplicateCategoryBoardTableComplete": "true", } func addBaseSettings(m map[string]string) map[string]string { From 56954e0491844a956ac095f63b97d72b68aa2523 Mon Sep 17 00:00:00 2001 From: Asaad Mahmood Date: Sat, 4 Mar 2023 12:20:05 +0500 Subject: [PATCH 020/102] Updating welcome screen for small sizes (#4609) --- .../__snapshots__/welcomePage.test.tsx.snap | 112 ++++++++++-------- webapp/src/pages/welcome/welcomePage.scss | 21 +++- webapp/src/pages/welcome/welcomePage.tsx | 104 ++++++++-------- 3 files changed, 138 insertions(+), 99 deletions(-) diff --git a/webapp/src/pages/welcome/__snapshots__/welcomePage.test.tsx.snap b/webapp/src/pages/welcome/__snapshots__/welcomePage.test.tsx.snap index 2dfc52f90..ef9ac5df4 100644 --- a/webapp/src/pages/welcome/__snapshots__/welcomePage.test.tsx.snap +++ b/webapp/src/pages/welcome/__snapshots__/welcomePage.test.tsx.snap @@ -18,32 +18,40 @@ exports[`pages/welcome Welcome Page shows Explore Page 1`] = ` > Boards is a project management tool that helps define, organize, track, and manage work across teams using a familiar Kanban board view. - Boards Welcome Image - Boards Welcome Image - -
+ Boards Welcome Image +
+ + +
+ @@ -67,32 +75,40 @@ exports[`pages/welcome Welcome Page shows Explore Page with subpath 1`] = ` > Boards is a project management tool that helps define, organize, track, and manage work across teams using a familiar Kanban board view. - Boards Welcome Image - Boards Welcome Image - - + Boards Welcome Image +
+ + +
+ diff --git a/webapp/src/pages/welcome/welcomePage.scss b/webapp/src/pages/welcome/welcomePage.scss index d6810e1bf..ebeb7f2b6 100644 --- a/webapp/src/pages/welcome/welcomePage.scss +++ b/webapp/src/pages/welcome/welcomePage.scss @@ -10,6 +10,26 @@ @media (max-height: 768px) { justify-content: flex-start; height: auto; + padding-top: 40px; + } + + .WelcomePage__content { + display: flex; + flex-direction: column; + align-items: center; + gap: 12px; + + @media (max-height: 800px) { + flex-direction: column-reverse; + margin-top: 16px; + } + } + + .WelcomePage__buttons { + display: flex; + flex-direction: column; + align-items: center; + gap: 12px; } > div { @@ -34,7 +54,6 @@ } .skip { - margin-top: 12px; color: rgba(var(--link-color-rgb), 1); cursor: pointer; diff --git a/webapp/src/pages/welcome/welcomePage.tsx b/webapp/src/pages/welcome/welcomePage.tsx index df7a6edbf..723f5c3f5 100644 --- a/webapp/src/pages/welcome/welcomePage.tsx +++ b/webapp/src/pages/welcome/welcomePage.tsx @@ -127,59 +127,63 @@ const WelcomePage = () => { /> - {/* This image will be rendered on large screens over 2000px */} - Boards Welcome Image +
+ {/* This image will be rendered on large screens over 2000px */} + Boards Welcome Image - {/* This image will be rendered on small screens below 2000px */} - Boards Welcome Image + {/* This image will be rendered on small screens below 2000px */} + Boards Welcome Image - {me?.is_guest !== true && - } +
+ {me?.is_guest !== true && + } - {me?.is_guest !== true && - - - } - {me?.is_guest === true && - } + {me?.is_guest !== true && + + + } + {me?.is_guest === true && + } +
+
) From 24d6ad48e7cc7b35daba309dc7993bb4103711f7 Mon Sep 17 00:00:00 2001 From: Vidar Haarr Date: Fri, 3 Mar 2023 14:25:16 +0100 Subject: [PATCH 021/102] =?UTF-8?q?Translated=20using=20Weblate=20(Norwegi?= =?UTF-8?q?an=20Bokm=C3=A5l)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 40.6% (183 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/nb_NO/ --- webapp/i18n/nb_NO.json | 169 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 164 insertions(+), 5 deletions(-) diff --git a/webapp/i18n/nb_NO.json b/webapp/i18n/nb_NO.json index 3b6c0ce38..604a40885 100644 --- a/webapp/i18n/nb_NO.json +++ b/webapp/i18n/nb_NO.json @@ -1,14 +1,42 @@ { + "AppBar.Tooltip": "Veksle lenkede tavler", + "Attachment.Attachment-title": "Vedlegg", + "AttachmentBlock.DeleteAction": "slett", + "AttachmentBlock.addElement": "legg til {type}", + "AttachmentBlock.delete": "Vedlegg slettet.", + "AttachmentBlock.failed": "Denne filen kunne ikke lastes opp fordi størrelsesgrensen er nådd.", + "AttachmentBlock.upload": "Vedlegg lastes opp.", + "AttachmentBlock.uploadSuccess": "Vedlegg lastet opp.", + "AttachmentElement.delete-confirmation-dialog-button-text": "Slett", + "AttachmentElement.download": "Last ned", + "AttachmentElement.upload-percentage": "Laster opp ...({uploadPercent}%)", "BoardComponent.add-a-group": "+ Legg til gruppe", "BoardComponent.delete": "Slett", "BoardComponent.hidden-columns": "Skjulte kolonner", "BoardComponent.hide": "Skjul", "BoardComponent.new": "+ Ny", "BoardComponent.no-property": "Ingen {property}", - "BoardComponent.no-property-title": "Elementer med en tom {property} område kommer hit. Denne kolonnen kan ikke fjernes.", + "BoardComponent.no-property-title": "Elementer med tom {property} atributt legges her. Denne kolonnen kan ikke fjernes.", "BoardComponent.show": "Vis", + "BoardMember.schemeAdmin": "Admin", + "BoardMember.schemeCommenter": "Kommentator", + "BoardMember.schemeEditor": "Redaktør", + "BoardMember.schemeNone": "Ingen", + "BoardMember.schemeViewer": "Viser", + "BoardMember.unlinkChannel": "Fjern lenke", "BoardPage.newVersion": "En ny versjon av Boards er tilgjengelig, klikk her for å laste inn på nytt.", "BoardPage.syncFailed": "Tavle kan slettes eller adgangen trekkes tilbake.", + "BoardTemplateSelector.add-template": "Lag ny mal", + "BoardTemplateSelector.create-empty-board": "Opprett tom tavle", + "BoardTemplateSelector.delete-template": "Slett", + "BoardTemplateSelector.description": "Legg til en tavle til sidestolpen med hvilken mal du vil fra listen under, eller start med en helt tom tavle.", + "BoardTemplateSelector.edit-template": "Rediger", + "BoardTemplateSelector.plugin.no-content-description": "Legg til en tavle i sidestolpen med hvilken mal du vil, eller start med en tom tavle.", + "BoardTemplateSelector.plugin.no-content-title": "Lag ny tavle", + "BoardTemplateSelector.title": "Lag ny tavle", + "BoardTemplateSelector.use-this-template": "Bruk denne malen", + "BoardsSwitcher.Title": "Finn tavle", + "BoardsUnfurl.Limited": "Flere detaljer er skjult fordi kortet er arkivert", "BoardsUnfurl.Remainder": "+{remainder} mer", "BoardsUnfurl.Updated": "Oppdatert {time}", "Calculations.Options.average.displayName": "Gjennomsnitt", @@ -16,11 +44,142 @@ "Calculations.Options.count.displayName": "Antall", "Calculations.Options.count.label": "Antall", "Calculations.Options.countChecked.displayName": "Avkrysset", - "Calculations.Options.countChecked.label": "Antall avsjekket", + "Calculations.Options.countChecked.label": "Antall valgt", "Calculations.Options.countUnchecked.displayName": "Ikke avmerket", - "Calculations.Options.countUnchecked.label": "Antall Ikke Avmerket", + "Calculations.Options.countUnchecked.label": "Antall ikke valgt", "Calculations.Options.countUniqueValue.displayName": "Unik", - "Calculations.Options.countUniqueValue.label": "Antall Unike Verdier", + "Calculations.Options.countUniqueValue.label": "Antall unike verdier", "Calculations.Options.countValue.displayName": "Verdier", - "Calculations.Options.countValue.label": "Antall Verdier" + "Calculations.Options.countValue.label": "Antall verdier", + "Calculations.Options.dateRange.displayName": "Tidsrom", + "Calculations.Options.dateRange.label": "Tidsrom", + "Calculations.Options.earliest.displayName": "Tiligst", + "Calculations.Options.earliest.label": "Tiligst", + "Calculations.Options.latest.displayName": "Senest", + "Calculations.Options.latest.label": "Senest", + "Calculations.Options.max.displayName": "Maks", + "Calculations.Options.max.label": "Maks", + "Calculations.Options.median.displayName": "Median", + "Calculations.Options.median.label": "Median", + "Calculations.Options.min.displayName": "Min", + "Calculations.Options.min.label": "Min", + "Calculations.Options.none.displayName": "Kalkulèr", + "Calculations.Options.none.label": "Ingen", + "Calculations.Options.percentChecked.displayName": "Valgt", + "Calculations.Options.percentChecked.label": "Prosent valgt", + "Calculations.Options.percentUnchecked.displayName": "Ikke valgt", + "Calculations.Options.percentUnchecked.label": "Prosent ikke valgt", + "Calculations.Options.range.displayName": "Tidsrom", + "Calculations.Options.range.label": "Tidsrom", + "Calculations.Options.sum.displayName": "Sum", + "Calculations.Options.sum.label": "Sum", + "CalendarCard.untitled": "Uten navn", + "CardActionsMenu.copiedLink": "Kopiert!", + "CardActionsMenu.copyLink": "Kopier lenke", + "CardActionsMenu.delete": "Slett", + "CardActionsMenu.duplicate": "Dupliser", + "CardBadges.title-checkboxes": "Avkrysningsbokser", + "CardBadges.title-comments": "Kommentarer", + "CardBadges.title-description": "Dette kortet har en beskrivelsestekst", + "CardDetail.Attach": "Legg ved", + "CardDetail.Follow": "Følg", + "CardDetail.Following": "Følger", + "CardDetail.add-content": "Legg til innhold", + "CardDetail.add-icon": "Legg til ikon", + "CardDetail.add-property": "+ Legg til en verdi", + "CardDetail.addCardText": "legg inn tekst i kortet", + "CardDetail.limited-body": "Oppgrader til vår profesjonelle eller bedriftsplan.", + "CardDetail.limited-button": "Oppgrader", + "CardDetail.limited-title": "Dette kortet er skjult", + "CardDetail.moveContent": "Flytt innholdet", + "CardDetail.new-comment-placeholder": "Legg til kommentar ...", + "CardDetailProperty.confirm-delete-heading": "Bekreft sletting av verdi", + "CardDetailProperty.confirm-delete-subtext": "Er du sikker på at du vil slette verdien \"{propertyName}\"? Dette vil fjerne verdien fra alle kortene på denne tavlen.", + "CardDetailProperty.confirm-property-name-change-subtext": "Er du sikker på at du vil endre verdien \"{propertyName}\" {customText}? Dette vil påvirke verdien på {numOfCards} kort på denne tavlen, og kan forårsake at du mister informasjon.", + "CardDetailProperty.confirm-property-type-change": "Bekreft endring av verditype", + "CardDetailProperty.delete-action-button": "Slett", + "CardDetailProperty.property-change-action-button": "Endre verdi", + "CardDetailProperty.property-changed": "Verdi endret!", + "CardDetailProperty.property-deleted": "Fjernet {propertyName}!", + "CardDetailProperty.property-name-change-subtext": "type fra \"{oldPropType}\" til \"{newPropType}\"", + "CardDetial.limited-link": "Lær mer om våre planer.", + "CardDialog.delete-confirmation-dialog-attachment": "Bekreft sletting av vedlegg", + "CardDialog.delete-confirmation-dialog-button-text": "Slett", + "CardDialog.delete-confirmation-dialog-heading": "Bekreft sletting av kort", + "CardDialog.editing-template": "Du redigerer en mal.", + "CardDialog.nocard": "Dette kortet eksisterer ikke eller du har ikke tilgang.", + "Categories.CreateCategoryDialog.CancelText": "Avbryt", + "Categories.CreateCategoryDialog.CreateText": "Opprett", + "Categories.CreateCategoryDialog.Placeholder": "Navngi kategorien", + "Categories.CreateCategoryDialog.UpdateText": "Oppdater", + "CenterPanel.Login": "Logg inn", + "CenterPanel.Share": "Del", + "ChannelIntro.CreateBoard": "Opprett tavle", + "CloudMessage.cloud-server": "Få din egen gratis skytjener.", + "ColorOption.selectColor": "Velg {color} farge", + "Comment.delete": "Slett", + "CommentsList.send": "Send", + "ConfirmPerson.empty": "Tom", + "ConfirmPerson.search": "Søk ...", + "ConfirmationDialog.cancel-action": "Avbryt", + "ConfirmationDialog.confirm-action": "Bekreft", + "ContentBlock.Delete": "Slett", + "ContentBlock.DeleteAction": "slett", + "ContentBlock.addElement": "legg til {type}", + "ContentBlock.checkbox": "avkrysningsboks", + "ContentBlock.divider": "avdeler", + "ContentBlock.editCardCheckbox": "krysset-boks", + "ContentBlock.editCardCheckboxText": "rediger kort tekst", + "ContentBlock.editCardText": "rediger kort tekst", + "ContentBlock.editText": "Rediger tekst ...", + "ContentBlock.image": "bilde", + "ContentBlock.insertAbove": "Sett inn over", + "ContentBlock.moveBlock": "flytt kort innhold", + "ContentBlock.moveDown": "Flytt ned", + "ContentBlock.moveUp": "Flytt opp", + "ContentBlock.text": "tekst", + "DateRange.clear": "Tøm", + "DateRange.empty": "Tom", + "DateRange.endDate": "Sluttdato", + "DateRange.today": "I dag", + "DeleteBoardDialog.confirm-cancel": "Avbryt", + "DeleteBoardDialog.confirm-delete": "Slett", + "DeleteBoardDialog.confirm-info": "Er du sikker på at du vil slette tavlen \"{boardTitle}\"? Dette vil slette alle kortene på tavlen.", + "DeleteBoardDialog.confirm-info-template": "Er du sikker på at du vil slette tavlemalen \"{boardTitle}\"?", + "DeleteBoardDialog.confirm-tite": "Bekreft sletting av tavle", + "DeleteBoardDialog.confirm-tite-template": "Bekreft sletting av tavlemal", + "Dialog.closeDialog": "Lukk", + "EditableDayPicker.today": "I dag", + "Error.mobileweb": "Støtte for bruk i nettleser på mobil er i tidlig beta. Alt vil ikke fungere.", + "Error.websocket-closed": "Problemer med kobling til tjeneren. Sjekk konfigurasjonen hvis problemet vedvarer.", + "Filter.contains": "inneholder", + "Filter.ends-with": "ender med", + "Filter.includes": "inkluderer", + "Filter.is": "er", + "Filter.is-empty": "er tom", + "Filter.is-not-empty": "er ikke tom", + "Filter.is-not-set": "er ikke satt", + "Filter.is-set": "er satt", + "Filter.not-contains": "inkluderer ikke", + "Filter.not-ends-with": "ender ikke med", + "Filter.not-includes": "inkluderer ikke", + "Filter.not-starts-with": "starter ikke med", + "Filter.starts-with": "starter med", + "FilterByText.placeholder": "filtrer tekst", + "FilterComponent.add-filter": "+ Nytt filter", + "FilterComponent.delete": "Slett", + "FilterValue.empty": "(tom)", + "FindBoardsDialog.IntroText": "Søk etter tavle", + "FindBoardsDialog.NoResultsFor": "Ingen resultat for \"{searchQuery}\"", + "FindBoardsDialog.NoResultsSubtext": "Sjekk stavingen eller søk på noe annet.", + "FindBoardsDialog.SubTitle": "Skriv for å finne en tavle. Bruk opp/ned for å navigere. Enter for å velge, eller Esc for å avbryte", + "FindBoardsDialog.Title": "Finn tavle", + "GroupBy.hideEmptyGroups": "Skjul {count} tomme grupper", + "GroupBy.showHiddenGroups": "Vis {count} tomme grupper", + "GroupBy.ungroup": "Fjern fra gruppe", + "HideBoard.MenuOption": "Skjul tavlen", + "KanbanCard.untitled": "Uten navn", + "Mutator.new-board-from-template": "ny tavle fra mal", + "Mutator.new-card-from-template": "nytt kort fra mal", + "Mutator.new-template-from-card": "ny mal fra kort" } From 8fe781a16cbe7231372c48b741b9955e64ee598f Mon Sep 17 00:00:00 2001 From: Dmitry Scherbak Date: Fri, 3 Mar 2023 14:25:16 +0100 Subject: [PATCH 022/102] Translated using Weblate (Russian) Currently translated at 75.7% (341 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/ru/ --- webapp/i18n/ru.json | 45 ++++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/webapp/i18n/ru.json b/webapp/i18n/ru.json index b2a7419f8..f6b502b65 100644 --- a/webapp/i18n/ru.json +++ b/webapp/i18n/ru.json @@ -2,14 +2,14 @@ "AppBar.Tooltip": "Переключить связанные доски", "Attachment.Attachment-title": "Вложение", "AttachmentBlock.DeleteAction": "Удалить", - "AttachmentBlock.addElement": "добавить", - "AttachmentBlock.delete": "Вложение успешно удалено.", - "AttachmentBlock.failed": "Не удалось загрузить файл. Достигнут предел размера вложения.", + "AttachmentBlock.addElement": "добавить {type}", + "AttachmentBlock.delete": "Вложение удалено.", + "AttachmentBlock.failed": "Не удалось загрузить файл, так как превышена квота на размер файла.", "AttachmentBlock.upload": "Загрузка вложения.", - "AttachmentBlock.uploadSuccess": "Вложение успешно загружено.", + "AttachmentBlock.uploadSuccess": "Вложение загружено.", "AttachmentElement.delete-confirmation-dialog-button-text": "Удалить", "AttachmentElement.download": "Скачать", - "AttachmentElement.upload-percentage": "Загрузка", + "AttachmentElement.upload-percentage": "Загрузка...({uploadPercent}%)", "BoardComponent.add-a-group": "+ Добавить группу", "BoardComponent.delete": "Удалить", "BoardComponent.hidden-columns": "Скрытые столбцы", @@ -31,12 +31,12 @@ "BoardTemplateSelector.delete-template": "Удалить", "BoardTemplateSelector.description": "Добавьте доску на боковую панель, используя любой из шаблонов, описанных ниже, или начните с нуля.", "BoardTemplateSelector.edit-template": "Изменить", - "BoardTemplateSelector.plugin.no-content-description": "Добавьте доску на боковую панель, используя любой из указанных ниже шаблонов, или начните с нуля.{lineBreak} Участники \"{teamName}\" будут иметь доступ к созданным здесь доскам.", + "BoardTemplateSelector.plugin.no-content-description": "Добавьте доску на боковую панель, используя любой из указанных ниже шаблонов, или начните с нуля.", "BoardTemplateSelector.plugin.no-content-title": "Создать доску", "BoardTemplateSelector.title": "Создать доску", "BoardTemplateSelector.use-this-template": "Использовать этот шаблон", "BoardsSwitcher.Title": "Найти доски", - "BoardsUnfurl.Limited": "Информация скрыта в связи с тем, что карточка находится в архиве", + "BoardsUnfurl.Limited": "Информация скрыта, потому что карточка находится в архиве", "BoardsUnfurl.Remainder": "+{remainder} ещё", "BoardsUnfurl.Updated": "Обновлено {time}", "Calculations.Options.average.displayName": "Среднее", @@ -103,9 +103,9 @@ "CardDetailProperty.property-deleted": "{propertyName} успешно удалено!", "CardDetailProperty.property-name-change-subtext": "тип из \"{oldPropType}\" в \"{newPropType}\"", "CardDetial.limited-link": "Узнайте больше о наших планах.", - "CardDialog.delete-confirmation-dialog-attachment": "Подтвердите удаление вложения!", + "CardDialog.delete-confirmation-dialog-attachment": "Подтвердите удаление вложения", "CardDialog.delete-confirmation-dialog-button-text": "Удалить", - "CardDialog.delete-confirmation-dialog-heading": "Подтвердите удаление карточки!", + "CardDialog.delete-confirmation-dialog-heading": "Подтвердите удаление карточки", "CardDialog.editing-template": "Вы редактируете шаблон.", "CardDialog.nocard": "Эта карточка не существует или недоступна.", "Categories.CreateCategoryDialog.CancelText": "Отмена", @@ -114,10 +114,13 @@ "Categories.CreateCategoryDialog.UpdateText": "Обновить", "CenterPanel.Login": "Логин", "CenterPanel.Share": "Поделиться", + "ChannelIntro.CreateBoard": "Создать доску", "CloudMessage.cloud-server": "Получите свой бесплатный облачный сервер.", "ColorOption.selectColor": "Выберите цвет {color}", "Comment.delete": "Удалить", "CommentsList.send": "Отправить", + "ConfirmPerson.empty": "Пусто", + "ConfirmPerson.search": "Поиск...", "ConfirmationDialog.cancel-action": "Отмена", "ConfirmationDialog.confirm-action": "Подтвердить", "ContentBlock.Delete": "Удалить", @@ -165,6 +168,7 @@ "FilterByText.placeholder": "фильтровать текст", "FilterComponent.add-filter": "+ Добавить фильтр", "FilterComponent.delete": "Удалить", + "FilterValue.empty": "(пусто)", "FindBoardsDialog.IntroText": "Поиск досок", "FindBoardsDialog.NoResultsFor": "Нет результатов для \"{searchQuery}\"", "FindBoardsDialog.NoResultsSubtext": "Проверьте правильность написания или попробуйте другой запрос.", @@ -183,7 +187,7 @@ "OnboardingTour.AddComments.Title": "Добавить комментарии", "OnboardingTour.AddDescription.Body": "Добавьте описание к своей карточке, чтобы Ваши коллеги по команде знали, о чем эта карточка.", "OnboardingTour.AddDescription.Title": "Добавить описание", - "OnboardingTour.AddProperties.Body": "Добавляйте различные свойства карточкам, чтобы сделать их более мощными!", + "OnboardingTour.AddProperties.Body": "Добавляйте различные свойства карточкам, чтобы сделать их более значительными.", "OnboardingTour.AddProperties.Title": "Добавить свойства", "OnboardingTour.AddView.Body": "Перейдите сюда, чтобы создать новый вид для организации доски с использованием различных макетов.", "OnboardingTour.AddView.Title": "Добавить новый вид", @@ -284,6 +288,7 @@ "TableHeaderMenu.insert-right": "Вставить справа", "TableHeaderMenu.sort-ascending": "Сортировать по возрастанию", "TableHeaderMenu.sort-descending": "Сортировать по убыванию", + "TableRow.DuplicateCard": "дублировать карточку", "TableRow.MoreOption": "Больше действий", "TableRow.open": "Открыть", "TopBar.give-feedback": "Дать обратную связь", @@ -351,10 +356,13 @@ "WelcomePage.Explore.Button": "Исследовать", "WelcomePage.Heading": "Добро пожаловать на Доски", "WelcomePage.NoThanks.Text": "Нет спасибо, сам разберусь", + "WelcomePage.StartUsingIt.Text": "Начать пользоваться", "Workspace.editing-board-template": "Вы редактируете шаблон доски.", + "badge.guest": "Гость", "boardSelector.confirm-link-board": "Привязать доску к каналу", "boardSelector.confirm-link-board-button": "Да, ссылка доски", - "boardSelector.confirm-link-board-subtext": "Связывание доски \"{boardName}\" с этим каналом даст всем участникам этого канала доступ на редактирование доски. Вы уверены, что хотите связать это?", + "boardSelector.confirm-link-board-subtext": "Связывание доски \"{boardName}\" с каналом даст всем участникам канала доступ на редактирование доски. Вы можете в любое время отвязать доску о канала.", + "boardSelector.confirm-link-board-subtext-with-other-channel": "Привязка \"{boardName}\" с каналом приведет к возможности её редактирования всеми участниками канала (существующими и новыми). Кроме гостей канала.{lineBreak} Эта доска сейчас связана с другим каналом. Он будет отключен, если вы решите изменить привязку.", "boardSelector.create-a-board": "Создать доску", "boardSelector.link": "Ссылка", "boardSelector.search-for-boards": "Поиск досок", @@ -363,6 +371,8 @@ "calendar.month": "Месяц", "calendar.today": "СЕГОДНЯ", "calendar.week": "Неделя", + "centerPanel.undefined": "Отсутствует {propertyName}", + "centerPanel.unknown-user": "Неизвестный пользователь", "cloudMessage.learn-more": "Учить больше", "createImageBlock.failed": "Не удалось загрузить файл. Достигнут предел размера файла.", "default-properties.badges": "Комментарии и описание", @@ -377,11 +387,15 @@ "error.team-undefined": "Не корректная команда.", "error.unknown": "Произошла ошибка.", "generic.previous": "Предыдущий", - "imagePaste.upload-failed": "Некоторые файлы не загружены. Достигнут предел размера файла", + "imagePaste.upload-failed": "Некоторые файлы не загружены из-за превышения квоты на размер файла.", "limitedCard.title": "Карточки скрыты", "login.log-in-button": "Вход в систему", "login.log-in-title": "Вход в систему", "login.register-button": "или создать аккаунт, если у Вас его нет", + "new_channel_modal.create_board.empty_board_description": "Создать новую пустую доску", + "new_channel_modal.create_board.empty_board_title": "Пустая доска", + "new_channel_modal.create_board.select_template_placeholder": "Выбрать шаблон", + "new_channel_modal.create_board.title": "Создать доску для этого канала", "notification-box-card-limit-reached.close-tooltip": "Отложить на 10 дней", "notification-box-card-limit-reached.contact-link": "уведомить Вашего администратора", "notification-box-card-limit-reached.link": "Перейти на платный тариф", @@ -389,13 +403,18 @@ "notification-box-cards-hidden.title": "Это действие скрыло другую карточку", "notification-box.card-limit-reached.not-admin.text": "Чтобы получить доступ к архивным карточкам, Вы можете {contactLink} перейти на платный тариф.", "notification-box.card-limit-reached.text": "Достигнут лимит карточки, чтобы просмотреть старые карточки, {link}", + "person.add-user-to-board": "Добавить {username} на доску", + "person.add-user-to-board-confirm-button": "Добавить доску", + "person.add-user-to-board-permissions": "Разрешения", + "person.add-user-to-board-question": "Вы хотите добавить {username} на доску?", "register.login-button": "или войти в систему, если у вас уже есть аккаунт", "register.signup-title": "Зарегистрируйте свой аккаунт", + "rhs-board-non-admin-msg": "Вы не являетесь администратором этой доски", "rhs-boards.add": "Добавить", "rhs-boards.last-update-at": "Последнее обновление: {datetime}", "rhs-boards.link-boards-to-channel": "Связать доски с {channelName}", "rhs-boards.linked-boards": "Связанные доски", - "rhs-boards.no-boards-linked-to-channel": "К каналу {channelName} пока не подключены доски.", + "rhs-boards.no-boards-linked-to-channel": "К каналу {channelName} пока не подключены доски", "rhs-boards.no-boards-linked-to-channel-description": "Доски — это инструмент управления проектами, который помогает определять, организовывать, отслеживать и управлять работой между командами, используя знакомое представление доски Канбан.", "rhs-boards.unlink-board": "Отвязать доску", "rhs-channel-boards-header.title": "Доски", From 6b5c263e5627ebbeeec4b14f83755d90308a148a Mon Sep 17 00:00:00 2001 From: Felipe Nogueira Date: Fri, 3 Mar 2023 14:25:16 +0100 Subject: [PATCH 023/102] Translated using Weblate (Portuguese (Brazil)) Currently translated at 94.2% (424 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/pt_BR/ --- webapp/i18n/pt_BR.json | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/webapp/i18n/pt_BR.json b/webapp/i18n/pt_BR.json index 5cc319d38..aa755dc2f 100644 --- a/webapp/i18n/pt_BR.json +++ b/webapp/i18n/pt_BR.json @@ -1,5 +1,12 @@ { - "AppBar.Tooltip": "Ativar Boards vinculados", + "AppBar.Tooltip": "Ativar boards vinculados", + "Attachment.Attachment-title": "Anexo", + "AttachmentBlock.DeleteAction": "apagar", + "AttachmentBlock.addElement": "adicionar {type}", + "AttachmentBlock.delete": "Anexo apagado.", + "AttachmentBlock.uploadSuccess": "Anexo enviado.", + "AttachmentElement.delete-confirmation-dialog-button-text": "Apagar", + "AttachmentElement.upload-percentage": "Enviando...({uploadPercent}%)", "BoardComponent.add-a-group": "+ Adicione um grupo", "BoardComponent.delete": "Excluir", "BoardComponent.hidden-columns": "Colunas ocultas", @@ -16,8 +23,8 @@ "BoardMember.unlinkChannel": "Desvincular", "BoardPage.newVersion": "Uma nova versão do Boards está disponível, clique aqui para recarregar.", "BoardPage.syncFailed": "O Board pode ter sido excluído ou o acesso revogado.", - "BoardTemplateSelector.add-template": "Novo modelo", - "BoardTemplateSelector.create-empty-board": "Criar board vazio", + "BoardTemplateSelector.add-template": "Criar novo modelo", + "BoardTemplateSelector.create-empty-board": "Criar um board vazio", "BoardTemplateSelector.delete-template": "Excluir", "BoardTemplateSelector.description": "Adicione um quadro à barra lateral usando qualquer um dos modelos definidos abaixo ou comece do zero.", "BoardTemplateSelector.edit-template": "Editar", @@ -25,7 +32,7 @@ "BoardTemplateSelector.plugin.no-content-title": "Criar um board", "BoardTemplateSelector.title": "Criar um board", "BoardTemplateSelector.use-this-template": "Use este template", - "BoardsSwitcher.Title": "Encontrar Boards", + "BoardsSwitcher.Title": "Encontrar boards", "BoardsUnfurl.Limited": "Detalhes adicionais estão ocultos devido ao cartão ter sido arquivado", "BoardsUnfurl.Remainder": "+{remainder} mais", "BoardsUnfurl.Updated": "Atualizado {time}", @@ -71,6 +78,7 @@ "CardBadges.title-checkboxes": "Caixa de seleção", "CardBadges.title-comments": "Comentários", "CardBadges.title-description": "Este cartão tem uma descrição", + "CardDetail.Attach": "Anexar", "CardDetail.Follow": "Seguir", "CardDetail.Following": "Seguindo", "CardDetail.add-content": "Adicionar conteúdo", @@ -102,10 +110,13 @@ "Categories.CreateCategoryDialog.UpdateText": "Atualizar", "CenterPanel.Login": "Login", "CenterPanel.Share": "Compartilhar", + "ChannelIntro.CreateBoard": "Criar um board", "CloudMessage.cloud-server": "Obtenha seu próprio cloud server de graça.", "ColorOption.selectColor": "Selecione {color} Cor", "Comment.delete": "Excluir", "CommentsList.send": "Enviar", + "ConfirmPerson.empty": "Vazio", + "ConfirmPerson.search": "Buscar...", "ConfirmationDialog.cancel-action": "Cancelar", "ConfirmationDialog.confirm-action": "Confirmar", "ContentBlock.Delete": "Excluir", @@ -181,6 +192,7 @@ "OnboardingTour.ShareBoard.Body": "Você pode compartilhar seu board internament, com seu time, ou public para permitir visibilidade fora da sua organização.", "OnboardingTour.ShareBoard.Title": "Compartilhar quadro", "PersonProperty.board-members": "Membros do Board", + "PersonProperty.me": "Eu", "PersonProperty.non-board-members": "Não membros do board", "PropertyMenu.Delete": "Excluir", "PropertyMenu.changeType": "Alterar tipo da propriedade", @@ -235,6 +247,7 @@ "Sidebar.import-archive": "Importar arquivo", "Sidebar.invite-users": "Convidar usuários", "Sidebar.logout": "Sair", + "Sidebar.new-category.badge": "Novo", "Sidebar.no-boards-in-category": "Nenhum board", "Sidebar.product-tour": "Tour pelo produto", "Sidebar.random-icons": "Ícones aleatórios", @@ -257,6 +270,7 @@ "SidebarTour.SidebarCategories.Body": "Todos seus boards agora são organizados sob sua nova barra lateral. Não é mais necessárioa alternar entre espaços de trabalho. Categorias personalizadas em suas estações prévias de trabalho foram automaticamente criadas para você como parte do seu upgrade para v7.2. Estas podem ser removidas ou editadas de acordo com a sua preferência.", "SidebarTour.SidebarCategories.Link": "Saiba mais", "SidebarTour.SidebarCategories.Title": "Categorias de barra lateral", + "SiteStats.total_boards": "Total de boards", "TableComponent.add-icon": "Adicionar Ícone", "TableComponent.name": "Nome", "TableComponent.plus-new": "+ Novo", @@ -267,6 +281,7 @@ "TableHeaderMenu.insert-right": "Inserir à direita", "TableHeaderMenu.sort-ascending": "Ordem ascendente", "TableHeaderMenu.sort-descending": "Ordem descendente", + "TableRow.MoreOption": "Mais ações", "TableRow.open": "Abrir", "TopBar.give-feedback": "Dar feedback", "URLProperty.copiedLink": "Copiado!", @@ -348,6 +363,7 @@ "calendar.month": "Mês", "calendar.today": "HOJE", "calendar.week": "Semana", + "centerPanel.unknown-user": "Usuário desconhecido", "cloudMessage.learn-more": "Saiba mais", "createImageBlock.failed": "Não foi possível enviar o arquivo. Limite de tamanho alcançado.", "default-properties.badges": "Comentários e descrição", @@ -369,6 +385,7 @@ "login.log-in-button": "Entrar", "login.log-in-title": "Entrar", "login.register-button": "ou criar uma conta se você ainda não tiver uma", + "new_channel_modal.create_board.select_template_placeholder": "Selecionar um modelo", "notification-box-card-limit-reached.close-tooltip": "Soneca por 10 dias", "notification-box-card-limit-reached.contact-link": "notificar seu admin", "notification-box-card-limit-reached.link": "Atualizar para um plano pago", @@ -388,14 +405,14 @@ "rhs-boards.dm": "DM", "rhs-boards.gm": "GM", "rhs-boards.header.dm": "esta Direct Message", - "rhs-boards.header.gm": "Este Gruop Message", + "rhs-boards.header.gm": "esta mensagem de grupo", "rhs-boards.last-update-at": "Última atualização em: {datetime}", "rhs-boards.link-boards-to-channel": "Vincular boards para {channelName}", "rhs-boards.linked-boards": "Boards vinculados", "rhs-boards.no-boards-linked-to-channel": "Nenhum board está vinculado a {channelName} ainda", "rhs-boards.no-boards-linked-to-channel-description": "Boards é uma ferramenta de gerenciamento de projeto que ajuda a definir, organizar, rastrear e gerenciar o trabalho entre times, usando uma visualização de quadro estilo Kaban familiar.", "rhs-boards.unlink-board": "Desvincular board", - "rhs-boards.unlink-board1": "Desvincular board Hello", + "rhs-boards.unlink-board1": "Desvincular board", "rhs-channel-boards-header.title": "Boards", "share-board.publish": "Publicar", "share-board.share": "Compartilhar", From d16bbcbe10fba7d525c836c7c84d3cacbe4eb3c1 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Mon, 6 Mar 2023 08:48:30 -0700 Subject: [PATCH 024/102] Fix table multiperson (#4613) * clear overflow on multiperson * clear overflow on multiperson --- webapp/src/components/table/table.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/webapp/src/components/table/table.scss b/webapp/src/components/table/table.scss index bbc9ef118..6d36a7215 100644 --- a/webapp/src/components/table/table.scss +++ b/webapp/src/components/table/table.scss @@ -203,6 +203,7 @@ width: inherit; } + .MultiPerson.octo-propertyvalue, .Person.octo-propertyvalue, .DateRange.octo-propertyvalue { overflow: unset; From fe29ec882619d0fd0fd2a271c605061d478c1a55 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Mon, 6 Mar 2023 12:26:39 -0700 Subject: [PATCH 025/102] check permissions to channel before patching via api --- server/app/boards.go | 13 +++++++++ server/app/boards_test.go | 61 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/server/app/boards.go b/server/app/boards.go index 2ddee918f..d31bd573c 100644 --- a/server/app/boards.go +++ b/server/app/boards.go @@ -355,12 +355,15 @@ func (a *App) PatchBoard(patch *model.BoardPatch, boardID, userID string) (*mode var oldMembers []*model.BoardMember if patch.Type != nil || patch.ChannelID != nil { + testChannel := "" if patch.ChannelID != nil && *patch.ChannelID == "" { var err error oldMembers, err = a.GetMembersForBoard(boardID) if err != nil { a.logger.Error("Unable to get the board members", mlog.Err(err)) } + } else if patch.ChannelID != nil && *patch.ChannelID != "" { + testChannel = *patch.ChannelID } board, err := a.store.GetBoard(boardID) @@ -372,7 +375,17 @@ func (a *App) PatchBoard(patch *model.BoardPatch, boardID, userID string) (*mode } oldChannelID = board.ChannelID isTemplate = board.IsTemplate + if testChannel == "" { + testChannel = oldChannelID + } + + if testChannel != "" { + if !a.permissions.HasPermissionToChannel(userID, testChannel, model.PermissionCreatePost) { + return nil, model.NewErrPermission("access denied to channel") + } + } } + updatedBoard, err := a.store.PatchBoard(boardID, patch, userID) if err != nil { return nil, err diff --git a/server/app/boards_test.go b/server/app/boards_test.go index fc9771e54..ee851fdb8 100644 --- a/server/app/boards_test.go +++ b/server/app/boards_test.go @@ -399,6 +399,67 @@ func TestPatchBoard(t *testing.T) { require.NoError(t, err) require.Equal(t, boardID, patchedBoard.ID) }) + + t.Run("patch type channel, user without post permissions", func(t *testing.T) { + const boardID = "board_id_1" + const userID = "user_id_2" + const teamID = "team_id_1" + + channelID := "myChannel" + patchType := model.BoardTypeOpen + patch := &model.BoardPatch{ + Type: &patchType, + ChannelID: &channelID, + } + + // Type not nil, will cause board to be reteived + // to check isTemplate + th.Store.EXPECT().GetBoard(boardID).Return(&model.Board{ + ID: boardID, + TeamID: teamID, + IsTemplate: true, + }, nil).Times(1) + + th.API.EXPECT().HasPermissionToChannel(userID, channelID, model.PermissionCreatePost).Return(false).Times(1) + _, err := th.App.PatchBoard(patch, boardID, userID) + require.Error(t, err) + }) + + t.Run("patch type remove channel, user without post permissions", func(t *testing.T) { + const boardID = "board_id_1" + const userID = "user_id_2" + const teamID = "team_id_1" + + channelID := "myChannel" + clearChannel := "" + patchType := model.BoardTypeOpen + patch := &model.BoardPatch{ + Type: &patchType, + ChannelID: &clearChannel, + } + + // Type not nil, will cause board to be reteived + // to check isTemplate + th.Store.EXPECT().GetBoard(boardID).Return(&model.Board{ + ID: boardID, + TeamID: teamID, + IsTemplate: true, + ChannelID: channelID, + }, nil).Times(2) + + th.API.EXPECT().HasPermissionToChannel(userID, channelID, model.PermissionCreatePost).Return(false).Times(1) + + th.API.EXPECT().HasPermissionToTeam(userID, teamID, model.PermissionManageTeam).Return(false).Times(1) + // Should call GetMembersForBoard 2 times + // for WS BroadcastBoardChange + // for AddTeamMembers check + // We are returning the user as a direct Board Member, so BroadcastMemberDelete won't be called + th.Store.EXPECT().GetMembersForBoard(boardID).Return([]*model.BoardMember{{BoardID: boardID, UserID: userID, SchemeEditor: true}}, nil).Times(1) + + _, err := th.App.PatchBoard(patch, boardID, userID) + require.Error(t, err) + }) + } func TestGetBoardCount(t *testing.T) { From 5ac5eadbeeecbfbcfe7db3e74726585f73b00d99 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Mon, 6 Mar 2023 15:10:58 -0700 Subject: [PATCH 026/102] adding a successful test --- server/app/boards_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/server/app/boards_test.go b/server/app/boards_test.go index ee851fdb8..7830c9297 100644 --- a/server/app/boards_test.go +++ b/server/app/boards_test.go @@ -185,6 +185,7 @@ func TestPatchBoard(t *testing.T) { // Type not null will retrieve team members th.Store.EXPECT().GetUsersByTeam(teamID, "", false, false).Return([]*model.User{}, nil) + th.Store.EXPECT().GetUserByID(userID).Return(&model.User{ID: userID, Username: "UserName"}, nil) th.Store.EXPECT().PatchBoard(boardID, patch, userID).Return( &model.Board{ @@ -425,6 +426,44 @@ func TestPatchBoard(t *testing.T) { require.Error(t, err) }) + t.Run("patch type channel, user with post permissions", func(t *testing.T) { + const boardID = "board_id_1" + const userID = "user_id_2" + const teamID = "team_id_1" + + channelID := "myChannel" + patch := &model.BoardPatch{ + ChannelID: &channelID, + } + + // Type not nil, will cause board to be reteived + // to check isTemplate + th.Store.EXPECT().GetBoard(boardID).Return(&model.Board{ + ID: boardID, + TeamID: teamID, + }, nil).Times(2) + + th.API.EXPECT().HasPermissionToChannel(userID, channelID, model.PermissionCreatePost).Return(true).Times(1) + + th.Store.EXPECT().PatchBoard(boardID, patch, userID).Return( + &model.Board{ + ID: boardID, + TeamID: teamID, + }, + nil) + + // Should call GetMembersForBoard 2 times + // - for WS BroadcastBoardChange + // - for AddTeamMembers check + th.Store.EXPECT().GetMembersForBoard(boardID).Return([]*model.BoardMember{}, nil).Times(2) + + th.Store.EXPECT().PostMessage(utils.Anything, "", "").Times(1) + + patchedBoard, err := th.App.PatchBoard(patch, boardID, userID) + require.NoError(t, err) + require.Equal(t, boardID, patchedBoard.ID) + }) + t.Run("patch type remove channel, user without post permissions", func(t *testing.T) { const boardID = "board_id_1" const userID = "user_id_2" From fa72286427d0d11bc10638625ad581795cfbc46f Mon Sep 17 00:00:00 2001 From: Harshil Sharma <18575143+harshilsharma63@users.noreply.github.com> Date: Tue, 7 Mar 2023 10:21:53 +0530 Subject: [PATCH 027/102] Board teamless file path (#4577) * Updated upload and donwload code * Removed archived file handling as we no longer have cloud limits * Fixed server lint * Restored unused * CI * Added new tests * Fixed integration tests * Added Path column for personal server's FileInfo table * Removed sophesticated, elegant debug logs --------- Co-authored-by: Mattermost Build --- server/api/api.go | 2 +- server/api/files.go | 27 +----- server/app/files.go | 41 ++++++++- server/app/files_test.go | 90 +++++++++++++++++-- server/client/client.go | 9 ++ server/services/store/sqlstore/file.go | 4 + .../000039_add_path_to_file_info.down.sql | 1 + .../000039_add_path_to_file_info.up.sql | 1 + server/utils/utils.go | 5 ++ 9 files changed, 145 insertions(+), 35 deletions(-) create mode 100644 server/services/store/sqlstore/migrations/000039_add_path_to_file_info.down.sql create mode 100644 server/services/store/sqlstore/migrations/000039_add_path_to_file_info.up.sql diff --git a/server/api/api.go b/server/api/api.go index ec376a9c0..be0287257 100644 --- a/server/api/api.go +++ b/server/api/api.go @@ -227,7 +227,7 @@ func jsonStringResponse(w http.ResponseWriter, code int, message string) { //nol fmt.Fprint(w, message) } -func jsonBytesResponse(w http.ResponseWriter, code int, json []byte) { +func jsonBytesResponse(w http.ResponseWriter, code int, json []byte) { //nolint:unparam setResponseHeader(w, "Content-Type", "application/json") w.WriteHeader(code) _, _ = w.Write(json) diff --git a/server/api/files.go b/server/api/files.go index d9f6aa109..bb0ddcfc7 100644 --- a/server/api/files.go +++ b/server/api/files.go @@ -123,37 +123,12 @@ func (a *API) handleServeFile(w http.ResponseWriter, r *http.Request) { auditRec.AddMeta("teamID", board.TeamID) auditRec.AddMeta("filename", filename) - fileInfo, err := a.app.GetFileInfo(filename) + fileInfo, fileReader, err := a.app.GetFile(board.TeamID, boardID, filename) if err != nil && !model.IsErrNotFound(err) { a.errorResponse(w, r, err) return } - if fileInfo != nil && fileInfo.Archived { - fileMetadata := map[string]interface{}{ - "archived": true, - "name": fileInfo.Name, - "size": fileInfo.Size, - "extension": fileInfo.Extension, - } - - data, jsonErr := json.Marshal(fileMetadata) - if jsonErr != nil { - a.logger.Error("failed to marshal archived file metadata", mlog.String("filename", filename), mlog.Err(jsonErr)) - a.errorResponse(w, r, jsonErr) - return - } - - jsonBytesResponse(w, http.StatusBadRequest, data) - return - } - - fileReader, err := a.app.GetFileReader(board.TeamID, boardID, filename) - if err != nil && !errors.Is(err, app.ErrFileNotFound) { - a.errorResponse(w, r, err) - return - } - if errors.Is(err, app.ErrFileNotFound) && board.ChannelID != "" { // prior to moving from workspaces to teams, the filepath was constructed from // workspaceID, which is the channel ID in plugin mode. diff --git a/server/app/files.go b/server/app/files.go index 081b78e14..1474a291a 100644 --- a/server/app/files.go +++ b/server/app/files.go @@ -7,6 +7,7 @@ import ( "path/filepath" "strings" + "github.com/mattermost/focalboard/server/model" mmModel "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/focalboard/server/utils" @@ -28,7 +29,7 @@ func (a *App) SaveFile(reader io.Reader, teamID, rootID, filename string) (strin createdFilename := utils.NewID(utils.IDTypeNone) fullFilename := fmt.Sprintf(`%s%s`, createdFilename, fileExtension) - filePath := filepath.Join(teamID, rootID, fullFilename) + filePath := filepath.Join(utils.GetBaseFilePath(), fullFilename) fileSize, appErr := a.filesBackend.WriteFile(reader, filePath) if appErr != nil { @@ -45,7 +46,7 @@ func (a *App) SaveFile(reader io.Reader, teamID, rootID, filename string) (strin CreateAt: now, UpdateAt: now, DeleteAt: 0, - Path: emptyString, + Path: filePath, ThumbnailPath: emptyString, PreviewPath: emptyString, Name: filename, @@ -59,6 +60,7 @@ func (a *App) SaveFile(reader io.Reader, teamID, rootID, filename string) (strin Content: "", RemoteId: nil, } + err := a.store.SaveFileInfo(fileInfo) if err != nil { return "", err @@ -77,6 +79,7 @@ func (a *App) GetFileInfo(filename string) (*mmModel.FileInfo, error) { // will be the fileinfo id. parts := strings.Split(filename, ".") fileInfoID := parts[0][1:] + fileInfo, err := a.store.GetFileInfo(fileInfoID) if err != nil { return nil, err @@ -85,6 +88,40 @@ func (a *App) GetFileInfo(filename string) (*mmModel.FileInfo, error) { return fileInfo, nil } +func (a *App) GetFile(teamID, rootID, fileName string) (*mmModel.FileInfo, filestore.ReadCloseSeeker, error) { + fileInfo, err := a.GetFileInfo(fileName) + if err != nil && !model.IsErrNotFound(err) { + a.logger.Error("111") + return nil, nil, err + } + + var filePath string + + if fileInfo != nil && fileInfo.Path != "" { + filePath = fileInfo.Path + } else { + filePath = filepath.Join(teamID, rootID, fileName) + } + + exists, err := a.filesBackend.FileExists(filePath) + if err != nil { + a.logger.Error(fmt.Sprintf("GetFile: Failed to check if file exists as path. Path: %s, error: %e", filePath, err)) + return nil, nil, err + } + + if !exists { + return nil, nil, ErrFileNotFound + } + + reader, err := a.filesBackend.Reader(filePath) + if err != nil { + a.logger.Error(fmt.Sprintf("GetFile: Failed to get file reader of existing file at path: %s, error: %e", filePath, err)) + return nil, nil, err + } + + return fileInfo, reader, nil +} + func (a *App) GetFileReader(teamID, rootID, filename string) (filestore.ReadCloseSeeker, error) { filePath := filepath.Join(teamID, rootID, filename) exists, err := a.filesBackend.FileExists(filePath) diff --git a/server/app/files_test.go b/server/app/files_test.go index 11e4991b8..b39327f7b 100644 --- a/server/app/files_test.go +++ b/server/app/files_test.go @@ -7,6 +7,7 @@ import ( "path/filepath" "strings" "testing" + "time" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" @@ -195,8 +196,8 @@ func TestSaveFile(t *testing.T) { writeFileFunc := func(reader io.Reader, path string) int64 { paths := strings.Split(path, string(os.PathSeparator)) - assert.Equal(t, "1", paths[0]) - assert.Equal(t, testBoardID, paths[1]) + assert.Equal(t, "boards", paths[0]) + assert.Equal(t, time.Now().Format("20060102"), paths[1]) fileName = paths[2] return int64(10) } @@ -219,8 +220,8 @@ func TestSaveFile(t *testing.T) { writeFileFunc := func(reader io.Reader, path string) int64 { paths := strings.Split(path, string(os.PathSeparator)) - assert.Equal(t, "1", paths[0]) - assert.Equal(t, "test-board-id", paths[1]) + assert.Equal(t, "boards", paths[0]) + assert.Equal(t, time.Now().Format("20060102"), paths[1]) assert.Equal(t, "jpg", strings.Split(paths[2], ".")[1]) return int64(10) } @@ -243,8 +244,8 @@ func TestSaveFile(t *testing.T) { writeFileFunc := func(reader io.Reader, path string) int64 { paths := strings.Split(path, string(os.PathSeparator)) - assert.Equal(t, "1", paths[0]) - assert.Equal(t, "test-board-id", paths[1]) + assert.Equal(t, "boards", paths[0]) + assert.Equal(t, time.Now().Format("20060102"), paths[1]) assert.Equal(t, "jpg", strings.Split(paths[2], ".")[1]) return int64(10) } @@ -304,3 +305,80 @@ func TestGetFileInfo(t *testing.T) { assert.Nil(t, fetchedFileInfo) }) } + +func TestGetFile(t *testing.T) { + th, _ := SetupTestHelper(t) + + t.Run("when FileInfo exists", func(t *testing.T) { + th.Store.EXPECT().GetFileInfo("fileInfoID").Return(&mmModel.FileInfo{ + Id: "fileInfoID", + Path: "/path/to/file/fileName.txt", + }, nil) + + mockedFileBackend := &mocks.FileBackend{} + th.App.filesBackend = mockedFileBackend + mockedReadCloseSeek := &mocks.ReadCloseSeeker{} + readerFunc := func(path string) filestore.ReadCloseSeeker { + return mockedReadCloseSeek + } + + readerErrorFunc := func(path string) error { + return nil + } + mockedFileBackend.On("Reader", "/path/to/file/fileName.txt").Return(readerFunc, readerErrorFunc) + mockedFileBackend.On("FileExists", "/path/to/file/fileName.txt").Return(true, nil) + + fileInfo, seeker, err := th.App.GetFile("teamID", "boardID", "7fileInfoID.txt") + assert.NoError(t, err) + assert.NotNil(t, fileInfo) + assert.NotNil(t, seeker) + }) + + t.Run("when FileInfo doesn't exist", func(t *testing.T) { + th.Store.EXPECT().GetFileInfo("fileInfoID").Return(nil, nil) + + mockedFileBackend := &mocks.FileBackend{} + th.App.filesBackend = mockedFileBackend + mockedReadCloseSeek := &mocks.ReadCloseSeeker{} + readerFunc := func(path string) filestore.ReadCloseSeeker { + return mockedReadCloseSeek + } + + readerErrorFunc := func(path string) error { + return nil + } + + mockedFileBackend.On("Reader", "teamID/boardID/7fileInfoID.txt").Return(readerFunc, readerErrorFunc) + mockedFileBackend.On("FileExists", "teamID/boardID/7fileInfoID.txt").Return(true, nil) + + fileInfo, seeker, err := th.App.GetFile("teamID", "boardID", "7fileInfoID.txt") + assert.NoError(t, err) + assert.Nil(t, fileInfo) + assert.NotNil(t, seeker) + }) + + t.Run("when FileInfo exists but FileInfo.Path is not set", func(t *testing.T) { + th.Store.EXPECT().GetFileInfo("fileInfoID").Return(&mmModel.FileInfo{ + Id: "fileInfoID", + Path: "", + }, nil) + + mockedFileBackend := &mocks.FileBackend{} + th.App.filesBackend = mockedFileBackend + mockedReadCloseSeek := &mocks.ReadCloseSeeker{} + readerFunc := func(path string) filestore.ReadCloseSeeker { + return mockedReadCloseSeek + } + + readerErrorFunc := func(path string) error { + return nil + } + mockedFileBackend.On("Reader", "teamID/boardID/7fileInfoID.txt").Return(readerFunc, readerErrorFunc) + mockedFileBackend.On("FileExists", "teamID/boardID/7fileInfoID.txt").Return(true, nil) + + fileInfo, seeker, err := th.App.GetFile("teamID", "boardID", "7fileInfoID.txt") + assert.NoError(t, err) + assert.NotNil(t, fileInfo) + assert.NotNil(t, seeker) + }) +} diff --git a/server/client/client.go b/server/client/client.go index 6be594f40..8c794ccfe 100644 --- a/server/client/client.go +++ b/server/client/client.go @@ -380,6 +380,8 @@ func (c *Client) GetCards(boardID string, page int, perPage int) ([]*model.Card, return nil, BuildErrorResponse(r, err) } + defer closeBody(r) + var cards []*model.Card if err := json.NewDecoder(r.Body).Decode(&cards); err != nil { return nil, BuildErrorResponse(r, err) @@ -398,6 +400,8 @@ func (c *Client) PatchCard(cardID string, cardPatch *model.CardPatch, disableNot return nil, BuildErrorResponse(r, err) } + defer closeBody(r) + var cardNew *model.Card if err := json.NewDecoder(r.Body).Decode(&cardNew); err != nil { return nil, BuildErrorResponse(r, err) @@ -412,6 +416,8 @@ func (c *Client) GetCard(cardID string) (*model.Card, *Response) { return nil, BuildErrorResponse(r, err) } + defer closeBody(r) + var card *model.Card if err := json.NewDecoder(r.Body).Decode(&card); err != nil { return nil, BuildErrorResponse(r, err) @@ -450,6 +456,7 @@ func (c *Client) DeleteCategory(teamID, categoryID string) *Response { return BuildErrorResponse(r, err) } + defer closeBody(r) return BuildResponse(r) } @@ -1049,6 +1056,7 @@ func (c *Client) HideBoard(teamID, categoryID, boardID string) *Response { return BuildErrorResponse(r, err) } + defer closeBody(r) return BuildResponse(r) } @@ -1058,5 +1066,6 @@ func (c *Client) UnhideBoard(teamID, categoryID, boardID string) *Response { return BuildErrorResponse(r, err) } + defer closeBody(r) return BuildResponse(r) } diff --git a/server/services/store/sqlstore/file.go b/server/services/store/sqlstore/file.go index c1e189f3d..5825244c9 100644 --- a/server/services/store/sqlstore/file.go +++ b/server/services/store/sqlstore/file.go @@ -22,6 +22,7 @@ func (s *SQLStore) saveFileInfo(db sq.BaseRunner, fileInfo *mmModel.FileInfo) er "extension", "size", "delete_at", + "path", "archived", ). Values( @@ -31,6 +32,7 @@ func (s *SQLStore) saveFileInfo(db sq.BaseRunner, fileInfo *mmModel.FileInfo) er fileInfo.Extension, fileInfo.Size, fileInfo.DeleteAt, + fileInfo.Path, false, ) @@ -57,6 +59,7 @@ func (s *SQLStore) getFileInfo(db sq.BaseRunner, id string) (*mmModel.FileInfo, "extension", "size", "archived", + "path", ). From(s.tablePrefix + "file_info"). Where(sq.Eq{"Id": id}) @@ -73,6 +76,7 @@ func (s *SQLStore) getFileInfo(db sq.BaseRunner, id string) (*mmModel.FileInfo, &fileInfo.Extension, &fileInfo.Size, &fileInfo.Archived, + &fileInfo.Path, ) if err != nil { diff --git a/server/services/store/sqlstore/migrations/000039_add_path_to_file_info.down.sql b/server/services/store/sqlstore/migrations/000039_add_path_to_file_info.down.sql new file mode 100644 index 000000000..027b7d63f --- /dev/null +++ b/server/services/store/sqlstore/migrations/000039_add_path_to_file_info.down.sql @@ -0,0 +1 @@ +SELECT 1; \ No newline at end of file diff --git a/server/services/store/sqlstore/migrations/000039_add_path_to_file_info.up.sql b/server/services/store/sqlstore/migrations/000039_add_path_to_file_info.up.sql new file mode 100644 index 000000000..af7d5e8fe --- /dev/null +++ b/server/services/store/sqlstore/migrations/000039_add_path_to_file_info.up.sql @@ -0,0 +1 @@ +{{ addColumnIfNeeded "file_info" "path" "varchar(512)" "" }} \ No newline at end of file diff --git a/server/utils/utils.go b/server/utils/utils.go index 7a1ad9763..46326dd66 100644 --- a/server/utils/utils.go +++ b/server/utils/utils.go @@ -2,6 +2,7 @@ package utils import ( "encoding/json" + "path" "reflect" "time" @@ -120,3 +121,7 @@ func DedupeStringArr(arr []string) []string { return dedupedArr } + +func GetBaseFilePath() string { + return path.Join("boards", time.Now().Format("20060102")) +} From dda3b8f13a521edbdfef6bc401db1762adccc223 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Tue, 7 Mar 2023 11:01:52 -0700 Subject: [PATCH 028/102] lint fixes --- server/app/boards_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/app/boards_test.go b/server/app/boards_test.go index 7830c9297..8cd3679f2 100644 --- a/server/app/boards_test.go +++ b/server/app/boards_test.go @@ -469,7 +469,7 @@ func TestPatchBoard(t *testing.T) { const userID = "user_id_2" const teamID = "team_id_1" - channelID := "myChannel" + const channelID = "myChannel" clearChannel := "" patchType := model.BoardTypeOpen patch := &model.BoardPatch{ @@ -498,7 +498,6 @@ func TestPatchBoard(t *testing.T) { _, err := th.App.PatchBoard(patch, boardID, userID) require.Error(t, err) }) - } func TestGetBoardCount(t *testing.T) { From e59b61937f8197bea16e7754205a130ebdcda83e Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Thu, 9 Mar 2023 11:20:32 +0530 Subject: [PATCH 029/102] Counting on specific column --- server/services/store/sqlstore/data_migrations.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/services/store/sqlstore/data_migrations.go b/server/services/store/sqlstore/data_migrations.go index 15d86129d..bbc7e2218 100644 --- a/server/services/store/sqlstore/data_migrations.go +++ b/server/services/store/sqlstore/data_migrations.go @@ -853,7 +853,7 @@ func (s *SQLStore) doesDuplicateCategoryBoardsExist() (bool, error) { Having("count(*) > 1") query := s.getQueryBuilder(s.db). - Select("COUNT(*)"). + Select("COUNT(user_id)"). FromSelect(subQuery, "duplicate_dataset") row := query.QueryRow() From 41fbd5fecc2e05152dfeb590676ce7d97e1c4510 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Thu, 9 Mar 2023 17:53:45 +0100 Subject: [PATCH 030/102] Enable cross-compilation of Linux webapp via Docker (#4528) Relates to: #4470 Co-authored-by: Mattermost Build --- Dockerfile.build | 36 +++++++++++++++++++----------------- Makefile | 4 ++-- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/Dockerfile.build b/Dockerfile.build index 6cf014765..922c28c1d 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -1,10 +1,10 @@ -# This dockerfile is used to build Focalboard for Linux -# it builds all the parts inside the container and the last stage just holds the -# package that can be extracted using docker cp command -# ie -# docker build -f Dockerfile.build --no-cache -t focalboard-build:dirty . -# docker run --rm -v /tmp/dist:/tmp -d --name test focalboard-build:dirty /bin/sh -c 'sleep 1000' -# docker cp test:/dist/focalboard-server-linux-amd64.tar.gz . +# This Dockerfile is used to build Focalboard for Linux. It builds all the parts inside the image +# and the last stage just holds the package which is then copied back to the host. +# +# docker buildx build -f Dockerfile.build --no-cache --platform linux/amd64 -t focalboard-build:dirty --output out . +# docker buildx build -f Dockerfile.build --no-cache --platform linux/arm64 -t focalboard-build:dirty --output out . +# +# Afterwards the packages can be found in the ./out folder. # build frontend FROM node:16.3.0@sha256:ca6daf1543242acb0ca59ff425509eab7defb9452f6ae07c156893db06c7a9a4 AS frontend @@ -12,8 +12,10 @@ FROM node:16.3.0@sha256:ca6daf1543242acb0ca59ff425509eab7defb9452f6ae07c156893db WORKDIR /webapp COPY webapp . -RUN npm install --no-optional -RUN npm run pack +### 'CPPFLAGS="-DPNG_ARM_NEON_OPT=0"' Needed To Avoid Bug Described in: https://github.com/imagemin/optipng-bin/issues/118#issuecomment-1019838562 +### Can be Removed when Ticket will be Closed +RUN CPPFLAGS="-DPNG_ARM_NEON_OPT=0" npm install --no-optional && \ + npm run pack # build backend and package FROM golang:1.18.3@sha256:b203dc573d81da7b3176264bfa447bd7c10c9347689be40540381838d75eebef AS backend @@ -21,13 +23,13 @@ FROM golang:1.18.3@sha256:b203dc573d81da7b3176264bfa447bd7c10c9347689be405403818 COPY . . COPY --from=frontend /webapp/pack webapp/pack +ARG TARGETARCH + # RUN apt-get update && apt-get install libgtk-3-dev libwebkit2gtk-4.0-dev -y -RUN make server-linux -RUN make server-linux-package-docker +RUN EXCLUDE_PLUGIN=true EXCLUDE_SERVER=true EXCLUDE_ENTERPRISE=true make server-linux arch=${TARGETARCH} +RUN make server-linux-package-docker arch=${TARGETARCH} -# just hold the packages to output later -FROM alpine:3.12@sha256:c75ac27b49326926b803b9ed43bf088bc220d22556de1bc5f72d742c91398f69 AS dist - -WORKDIR /dist - -COPY --from=backend /go/dist/focalboard-server-linux-amd64.tar.gz . +# Copy package back to host +FROM scratch AS dist +ARG TARGETARCH +COPY --from=backend /go/dist/focalboard-server-linux-${TARGETARCH}.tar.gz . diff --git a/Makefile b/Makefile index b6e13291c..9d74bef1f 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,7 @@ endif server-linux: setup-go-work ## Build server for Linux. mkdir -p bin/linux $(eval LDFLAGS += -X "github.com/mattermost/focalboard/server/model.Edition=linux") - cd server; env GOOS=linux GOARCH=amd64 go build -ldflags '$(LDFLAGS)' -tags '$(BUILD_TAGS)' -o ../bin/linux/focalboard-server ./main + cd server; env GOOS=linux GOARCH=$(arch) go build -ldflags '$(LDFLAGS)' -tags '$(BUILD_TAGS)' -o ../bin/linux/focalboard-server ./main server-docker: setup-go-work ## Build server for Docker Architectures. mkdir -p bin/docker @@ -101,7 +101,7 @@ server-linux-package-docker: cp NOTICE.txt package/${PACKAGE_FOLDER} cp webapp/NOTICE.txt package/${PACKAGE_FOLDER}/webapp-NOTICE.txt mkdir -p dist - cd package && tar -czvf ../dist/focalboard-server-linux-amd64.tar.gz ${PACKAGE_FOLDER} + cd package && tar -czvf ../dist/focalboard-server-linux-$(arch).tar.gz ${PACKAGE_FOLDER} rm -rf package generate: ## Install and run code generators. From 1c010eeb4aae51db0b87581069445f50dd957f8b Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Mon, 13 Mar 2023 18:11:41 -0600 Subject: [PATCH 031/102] Merge pull request #4635 from mattermost/fix-emoji fix path for static files (cherry picked from commit 9e1dd374f241bb21997aa92967d3fe66908d0494) --- webapp/src/widgets/emojiPicker.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/webapp/src/widgets/emojiPicker.tsx b/webapp/src/widgets/emojiPicker.tsx index 147fc1d82..6570e2e32 100644 --- a/webapp/src/widgets/emojiPicker.tsx +++ b/webapp/src/widgets/emojiPicker.tsx @@ -5,6 +5,8 @@ import React, {FC} from 'react' import 'emoji-mart/css/emoji-mart.css' import {Picker, BaseEmoji} from 'emoji-mart' +import {Utils} from '../utils' + import './emojiPicker.scss' import emojiSpirit from '../../static/emoji_spirit.png' @@ -20,7 +22,7 @@ const EmojiPicker: FC = (props: Props): JSX.Element => ( > props.onSelect(emoji.native)} - backgroundImageFn={() => emojiSpirit} + backgroundImageFn={() => Utils.buildURL(emojiSpirit, true)} /> ) From 3fa0e082191654156279cb8349c6f5e1f696b4c9 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Wed, 22 Mar 2023 13:28:00 -0600 Subject: [PATCH 032/102] Fix category dialog (#4657) * test merge * update Dialog color for SidebarCategory * add semicolon * use the lowercase dialog class --- webapp/src/components/sidebar/sidebarCategory.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/webapp/src/components/sidebar/sidebarCategory.scss b/webapp/src/components/sidebar/sidebarCategory.scss index 62eb4fb3e..24bdde230 100644 --- a/webapp/src/components/sidebar/sidebarCategory.scss +++ b/webapp/src/components/sidebar/sidebarCategory.scss @@ -6,6 +6,10 @@ margin-top: 0; } + .dialog { + color: rgba(var(--center-channel-color-rgb)); + } + .octo-sidebar-item { display: flex; flex-direction: row; From d8e1fb4832953fb31c54d4bc3542e2e4d4fe0fb7 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Wed, 22 Mar 2023 13:28:23 -0600 Subject: [PATCH 033/102] copy safe writeFileResponse into personal server/desktop (#4654) * copy safe writeFileResponse into personal server/desktop * lint fix --------- Co-authored-by: Mattermost Build --- server/api/files.go | 91 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/server/api/files.go b/server/api/files.go index bb0ddcfc7..c2a6eaa71 100644 --- a/server/api/files.go +++ b/server/api/files.go @@ -8,6 +8,8 @@ import ( "errors" "io" "net/http" + "net/url" + "strconv" "strings" "time" @@ -20,9 +22,30 @@ import ( mmModel "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/shared/mlog" - "github.com/mattermost/mattermost-server/v6/shared/web" ) +var UnsafeContentTypes = [...]string{ + "application/javascript", + "application/ecmascript", + "text/javascript", + "text/ecmascript", + "application/x-javascript", + "text/html", +} + +var MediaContentTypes = [...]string{ + "image/jpeg", + "image/png", + "image/bmp", + "image/gif", + "image/tiff", + "video/avi", + "video/mpeg", + "video/mp4", + "audio/mpeg", + "audio/wav", +} + // FileUploadResponse is the response to a file upload // swagger:model type FileUploadResponse struct { @@ -145,10 +168,74 @@ func (a *API) handleServeFile(w http.ResponseWriter, r *http.Request) { } defer fileReader.Close() - web.WriteFileResponse(filename, fileInfo.MimeType, fileInfo.Size, time.Now(), "", fileReader, false, w, r) + mimeType := "" + var fileSize int64 + if fileInfo != nil { + mimeType = fileInfo.MimeType + fileSize = fileInfo.Size + } + writeFileResponse(filename, mimeType, fileSize, time.Now(), "", fileReader, false, w, r) auditRec.Success() } +func writeFileResponse(filename string, contentType string, contentSize int64, + lastModification time.Time, webserverMode string, fileReader io.ReadSeeker, forceDownload bool, w http.ResponseWriter, r *http.Request) { + w.Header().Set("Cache-Control", "private, no-cache") + w.Header().Set("X-Content-Type-Options", "nosniff") + + if contentSize > 0 { + contentSizeStr := strconv.Itoa(int(contentSize)) + if webserverMode == "gzip" { + w.Header().Set("X-Uncompressed-Content-Length", contentSizeStr) + } else { + w.Header().Set("Content-Length", contentSizeStr) + } + } + + if contentType == "" { + contentType = "application/octet-stream" + } else { + for _, unsafeContentType := range UnsafeContentTypes { + if strings.HasPrefix(contentType, unsafeContentType) { + contentType = "text/plain" + break + } + } + } + + w.Header().Set("Content-Type", contentType) + + var toDownload bool + if forceDownload { + toDownload = true + } else { + isMediaType := false + + for _, mediaContentType := range MediaContentTypes { + if strings.HasPrefix(contentType, mediaContentType) { + isMediaType = true + break + } + } + + toDownload = !isMediaType + } + + filename = url.PathEscape(filename) + + if toDownload { + w.Header().Set("Content-Disposition", "attachment;filename=\""+filename+"\"; filename*=UTF-8''"+filename) + } else { + w.Header().Set("Content-Disposition", "inline;filename=\""+filename+"\"; filename*=UTF-8''"+filename) + } + + // prevent file links from being embedded in iframes + w.Header().Set("X-Frame-Options", "DENY") + w.Header().Set("Content-Security-Policy", "Frame-ancestors 'none'") + + http.ServeContent(w, r, filename, lastModification, fileReader) +} + func (a *API) getFileInfo(w http.ResponseWriter, r *http.Request) { // swagger:operation GET /files/teams/{teamID}/{boardID}/{filename}/info getFile // From a1df107b249d7e28efe7850597e0e3e5051a0ba2 Mon Sep 17 00:00:00 2001 From: Filipe Date: Wed, 22 Mar 2023 12:03:54 +0100 Subject: [PATCH 034/102] Translated using Weblate (Portuguese) Currently translated at 7.5% (34 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/pt/ Translated using Weblate (Portuguese) Currently translated at 7.3% (33 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/pt/ --- webapp/i18n/pt.json | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/webapp/i18n/pt.json b/webapp/i18n/pt.json index 54ffe071d..975ddbc47 100644 --- a/webapp/i18n/pt.json +++ b/webapp/i18n/pt.json @@ -2,11 +2,35 @@ "AppBar.Tooltip": "Alternar quadros vinculados", "Attachment.Attachment-title": "Anexo", "AttachmentBlock.DeleteAction": "Apagar", - "AttachmentBlock.addElement": "Adicionar {tipo}", + "AttachmentBlock.addElement": "Adicionar {type}", "AttachmentBlock.delete": "Anexo apagado.", "AttachmentBlock.failed": "Este arquivo não pôde ser carregado pois ultrapassou o tamanho limite.", "AttachmentBlock.upload": "Carregando anexo.", "AttachmentBlock.uploadSuccess": "Anexo carregado.", "AttachmentElement.delete-confirmation-dialog-button-text": "Apagar", - "AttachmentElement.download": "Baixar" + "AttachmentElement.download": "Baixar", + "BoardComponent.delete": "Apagar", + "BoardComponent.hidden-columns": "Colunas escondidas", + "BoardComponent.hide": "Esconder", + "BoardComponent.new": "+ Novo", + "BoardComponent.no-property": "Não {property}", + "BoardComponent.show": "Mostrar", + "BoardMember.schemeAdmin": "Admin", + "BoardMember.schemeCommenter": "Comentador", + "BoardMember.schemeEditor": "Editor", + "BoardMember.schemeNone": "Nenhum", + "BoardPage.newVersion": "Está disponível uma nova versão do Boards, clique aqui para recarregar.", + "BoardPage.syncFailed": "O Board pode ter sido apagado ou o acesso revogado.", + "BoardTemplateSelector.add-template": "Criar novo modelo", + "BoardTemplateSelector.create-empty-board": "Criar um board vazio", + "BoardTemplateSelector.delete-template": "Apagar", + "BoardTemplateSelector.edit-template": "Editar", + "BoardTemplateSelector.plugin.no-content-title": "Criar um board", + "BoardTemplateSelector.title": "Criar um board", + "BoardTemplateSelector.use-this-template": "Usar este modelo", + "BoardsSwitcher.Title": "Encontrar boards", + "Calculations.Options.average.label": "Média", + "shareBoard.members-select-group": "Membros", + "shareBoard.unknown-channel-display-name": "Canal desconhecido", + "tutorial_tip.ok": "Próximo" } From ec759ac17a88324e1e72cf43ff192802d56dd452 Mon Sep 17 00:00:00 2001 From: Kaya Zeren Date: Wed, 22 Mar 2023 12:03:55 +0100 Subject: [PATCH 035/102] Translated using Weblate (Turkish) Currently translated at 100.0% (450 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/tr/ --- webapp/i18n/tr.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/webapp/i18n/tr.json b/webapp/i18n/tr.json index 406721992..b3d14b065 100644 --- a/webapp/i18n/tr.json +++ b/webapp/i18n/tr.json @@ -221,7 +221,7 @@ "PropertyType.UpdatedTime": "Son güncelleme zamanı", "PropertyType.Url": "Adres", "PropertyValueElement.empty": "Boş", - "RegistrationLink.confirmRegenerateToken": "Bu işlem daha önce paylaşılmış bağlantıları geçersiz kılacak. Devam etmek istiyor musunuz?", + "RegistrationLink.confirmRegenerateToken": "Bu işlem daha önce paylaşılmış bağlantıları geçersiz kılacak. İlerlemek istiyor musunuz?", "RegistrationLink.copiedLink": "Kopyalandı!", "RegistrationLink.copyLink": "Bağlantıyı kopyala", "RegistrationLink.description": "Başkalarının hesap ekleyebilmesi için bu bağlantıyı paylaş:", @@ -232,7 +232,7 @@ "ShareBoard.ShareInternal": "İçeride paylaş", "ShareBoard.ShareInternalDescription": "İzni olan kullanıcılar bu bağlantıyı kullanabilecek.", "ShareBoard.Title": "Panoyu paylaş", - "ShareBoard.confirmRegenerateToken": "Bu işlem daha önce paylaşılmış bağlantıları geçersiz kılacak. Devam etmek istiyor musunuz?", + "ShareBoard.confirmRegenerateToken": "Bu işlem daha önce paylaşılmış bağlantıları geçersiz kılacak. İlerlemek istiyor musunuz?", "ShareBoard.copiedLink": "Kopyalandı!", "ShareBoard.copyLink": "Bağlantıyı kopyala", "ShareBoard.regenerate": "Kodu yeniden oluştur", @@ -395,6 +395,10 @@ "login.log-in-button": "Oturum aç", "login.log-in-title": "Oturum açın", "login.register-button": "ya da hesabınız yoksa bir hesap açın", + "new_channel_modal.create_board.empty_board_description": "Yeni boş bir pano oluştur", + "new_channel_modal.create_board.empty_board_title": "Boş pano", + "new_channel_modal.create_board.select_template_placeholder": "Bir kalıp seçin", + "new_channel_modal.create_board.title": "Bu kanal için bir pano oluştur", "notification-box-card-limit-reached.close-tooltip": "10 gün için sustur", "notification-box-card-limit-reached.contact-link": "yöneticinizi bilgilendirin", "notification-box-card-limit-reached.link": "Ücretli bir tarifeye geçin", From b3469c645c21be5a773716457fde5e66fc8138e8 Mon Sep 17 00:00:00 2001 From: Felipe Nogueira Date: Wed, 22 Mar 2023 12:03:55 +0100 Subject: [PATCH 036/102] Translated using Weblate (Portuguese (Brazil)) Currently translated at 96.4% (434 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/pt_BR/ --- webapp/i18n/pt_BR.json | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/webapp/i18n/pt_BR.json b/webapp/i18n/pt_BR.json index aa755dc2f..8e984b4b5 100644 --- a/webapp/i18n/pt_BR.json +++ b/webapp/i18n/pt_BR.json @@ -101,7 +101,7 @@ "CardDetailProperty.property-name-change-subtext": "digite de \"{oldPropType}\" para \"{newPropType}\"", "CardDetial.limited-link": "Saiba mais sobre nossos planos.", "CardDialog.delete-confirmation-dialog-button-text": "Excluir", - "CardDialog.delete-confirmation-dialog-heading": "Confirmar exclusão do card!", + "CardDialog.delete-confirmation-dialog-heading": "Confirmar exclusão do cartão", "CardDialog.editing-template": "Você está editando um template.", "CardDialog.nocard": "Esse card não existe ou não está acessível.", "Categories.CreateCategoryDialog.CancelText": "Cancelar", @@ -163,6 +163,7 @@ "FilterByText.placeholder": "filtrar texto", "FilterComponent.add-filter": "+ Adicionar filtro", "FilterComponent.delete": "Excluir", + "FilterValue.empty": "(vazio)", "FindBoardsDialog.IntroText": "Procurar por quadros", "FindBoardsDialog.NoResultsFor": "Sem resultado para \"{searchQuery}\"", "FindBoardsDialog.NoResultsSubtext": "Verifique a digitação ou tente outra busca.", @@ -271,6 +272,7 @@ "SidebarTour.SidebarCategories.Link": "Saiba mais", "SidebarTour.SidebarCategories.Title": "Categorias de barra lateral", "SiteStats.total_boards": "Total de boards", + "SiteStats.total_cards": "Total de cartões", "TableComponent.add-icon": "Adicionar Ícone", "TableComponent.name": "Nome", "TableComponent.plus-new": "+ Novo", @@ -368,7 +370,7 @@ "createImageBlock.failed": "Não foi possível enviar o arquivo. Limite de tamanho alcançado.", "default-properties.badges": "Comentários e descrição", "default-properties.title": "Título", - "error.back-to-home": "Volta para Home", + "error.back-to-home": "Volta para o início", "error.back-to-team": "Volta para o time", "error.board-not-found": "Quadro não encontrado.", "error.go-login": "Log in", @@ -385,7 +387,10 @@ "login.log-in-button": "Entrar", "login.log-in-title": "Entrar", "login.register-button": "ou criar uma conta se você ainda não tiver uma", + "new_channel_modal.create_board.empty_board_description": "Criar um novo quadro vazio", + "new_channel_modal.create_board.empty_board_title": "Quadro vazio", "new_channel_modal.create_board.select_template_placeholder": "Selecionar um modelo", + "new_channel_modal.create_board.title": "Criar um quadro para este canal", "notification-box-card-limit-reached.close-tooltip": "Soneca por 10 dias", "notification-box-card-limit-reached.contact-link": "notificar seu admin", "notification-box-card-limit-reached.link": "Atualizar para um plano pago", @@ -400,11 +405,11 @@ "person.add-user-to-board-warning": "{username} não é um membro de um board, e não será notificado.", "register.login-button": "ou entre se você já tem uma conta", "register.signup-title": "Registrar uma conta", - "rhs-board-non-admin-msg": "Você não é admin de um board", + "rhs-board-non-admin-msg": "Você não é um adminstrador do quadro", "rhs-boards.add": "Adicionar", "rhs-boards.dm": "DM", "rhs-boards.gm": "GM", - "rhs-boards.header.dm": "esta Direct Message", + "rhs-boards.header.dm": "esta mensagem direta", "rhs-boards.header.gm": "esta mensagem de grupo", "rhs-boards.last-update-at": "Última atualização em: {datetime}", "rhs-boards.link-boards-to-channel": "Vincular boards para {channelName}", From 1fff221da9e1ec5d6862aa3a3782eee2c77c78c8 Mon Sep 17 00:00:00 2001 From: Miguel de la Cruz Date: Mon, 27 Mar 2023 13:56:39 +0200 Subject: [PATCH 037/102] Adds escaping when normalizing table names for MySQL on DB helpers (#4653) Co-authored-by: Mattermost Build --- server/services/store/sqlstore/migrate.go | 32 +++++++++++++---------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/server/services/store/sqlstore/migrate.go b/server/services/store/sqlstore/migrate.go index d3fd7e3c5..da48b3a5c 100644 --- a/server/services/store/sqlstore/migrate.go +++ b/server/services/store/sqlstore/migrate.go @@ -319,7 +319,7 @@ func (s *SQLStore) GetTemplateHelperFuncs() template.FuncMap { func (s *SQLStore) genAddColumnIfNeeded(tableName, columnName, datatype, constraint string) (string, error) { tableName = addPrefixIfNeeded(tableName, s.tablePrefix) - normTableName := normalizeTablename(s.schemaName, tableName) + normTableName := s.normalizeTablename(tableName) switch s.dbType { case model.SqliteDBType: @@ -358,7 +358,7 @@ func (s *SQLStore) genAddColumnIfNeeded(tableName, columnName, datatype, constra func (s *SQLStore) genDropColumnIfNeeded(tableName, columnName string) (string, error) { tableName = addPrefixIfNeeded(tableName, s.tablePrefix) - normTableName := normalizeTablename(s.schemaName, tableName) + normTableName := s.normalizeTablename(tableName) switch s.dbType { case model.SqliteDBType: @@ -395,7 +395,7 @@ func (s *SQLStore) genDropColumnIfNeeded(tableName, columnName string) (string, func (s *SQLStore) genCreateIndexIfNeeded(tableName, columns string) (string, error) { indexName := getIndexName(tableName, columns) tableName = addPrefixIfNeeded(tableName, s.tablePrefix) - normTableName := normalizeTablename(s.schemaName, tableName) + normTableName := s.normalizeTablename(tableName) switch s.dbType { case model.SqliteDBType: @@ -435,7 +435,7 @@ func (s *SQLStore) genRenameTableIfNeeded(oldTableName, newTableName string) (st oldTableName = addPrefixIfNeeded(oldTableName, s.tablePrefix) newTableName = addPrefixIfNeeded(newTableName, s.tablePrefix) - normOldTableName := normalizeTablename(s.schemaName, oldTableName) + normOldTableName := s.normalizeTablename(oldTableName) vars := map[string]string{ "schema": s.schemaName, @@ -466,14 +466,14 @@ func (s *SQLStore) genRenameTableIfNeeded(oldTableName, newTableName string) (st case model.PostgresDBType: return replaceVars(` do $$ - begin + begin if (SELECT COUNT(table_name) FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '[[new_table_name]]' AND table_schema = '[[schema]]' - ) = 0 then + ) = 0 then ALTER TABLE [[norm_old_table_name]] RENAME TO [[new_table_name]]; end if; - end$$; + end$$; `, vars), nil default: return "", ErrUnsupportedDatabaseType @@ -482,7 +482,7 @@ func (s *SQLStore) genRenameTableIfNeeded(oldTableName, newTableName string) (st func (s *SQLStore) genRenameColumnIfNeeded(tableName, oldColumnName, newColumnName, dataType string) (string, error) { tableName = addPrefixIfNeeded(tableName, s.tablePrefix) - normTableName := normalizeTablename(s.schemaName, tableName) + normTableName := s.normalizeTablename(tableName) vars := map[string]string{ "schema": s.schemaName, @@ -516,15 +516,15 @@ func (s *SQLStore) genRenameColumnIfNeeded(tableName, oldColumnName, newColumnNa case model.PostgresDBType: return replaceVars(` do $$ - begin + begin if (SELECT COUNT(table_name) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '[[table_name]]' AND table_schema = '[[schema]]' AND column_name = '[[new_column_name]]' - ) = 0 then + ) = 0 then ALTER TABLE [[norm_table_name]] RENAME COLUMN [[old_column_name]] TO [[new_column_name]]; end if; - end$$; + end$$; `, vars), nil default: return "", ErrUnsupportedDatabaseType @@ -620,7 +620,7 @@ func (s *SQLStore) doesColumnExist(tableName, columnName string) (bool, error) { func (s *SQLStore) genAddConstraintIfNeeded(tableName, constraintName, constraintType, constraintDefinition string) (string, error) { tableName = addPrefixIfNeeded(tableName, s.tablePrefix) - normTableName := normalizeTablename(s.schemaName, tableName) + normTableName := s.normalizeTablename(tableName) var query string @@ -686,8 +686,12 @@ func addPrefixIfNeeded(s, prefix string) string { return s } -func normalizeTablename(schemaName, tableName string) string { - if schemaName != "" && !strings.HasPrefix(tableName, schemaName+".") { +func (s *SQLStore) normalizeTablename(tableName string) string { + if s.schemaName != "" && !strings.HasPrefix(tableName, s.schemaName+".") { + schemaName := s.schemaName + if s.dbType == model.MysqlDBType { + schemaName = "`" + schemaName + "`" + } tableName = schemaName + "." + tableName } return tableName From d7af2be765b169008bca81df0fc89a95c42f8626 Mon Sep 17 00:00:00 2001 From: Miguel de la Cruz Date: Mon, 27 Mar 2023 23:47:32 +0200 Subject: [PATCH 038/102] Test fixing main after mono-repo (#4669) --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/dev-release.yml | 28 ++++++++++++++-------------- .github/workflows/lint-server.yml | 2 +- .github/workflows/prod-release.yml | 24 ++++++++++++------------ 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 783c58582..1e15579f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,7 +44,7 @@ jobs: repository: "mattermost/mattermost-server" fetch-depth: "20" path: "mattermost-server" - ref : "master" + ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Set up Go uses: actions/setup-go@v3 with: @@ -74,7 +74,7 @@ jobs: repository: "mattermost/mattermost-server" fetch-depth: "20" path: "mattermost-server" - ref : "master" + ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: npm ci run: | cd focalboard/webapp && npm ci && cd - @@ -132,7 +132,7 @@ jobs: repository: "mattermost/mattermost-server" fetch-depth: "20" path: "mattermost-server" - ref : "master" + ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Set up Go uses: actions/setup-go@v3 @@ -169,7 +169,7 @@ jobs: repository: "mattermost/mattermost-server" fetch-depth: "20" path: "mattermost-server" - ref : "master" + ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Set up Go uses: actions/setup-go@v3 diff --git a/.github/workflows/dev-release.yml b/.github/workflows/dev-release.yml index 9ebf34df6..e3ad2ed85 100644 --- a/.github/workflows/dev-release.yml +++ b/.github/workflows/dev-release.yml @@ -8,14 +8,14 @@ on: workflow_dispatch: env: - BRANCH_NAME: ${{ github.head_ref || github.ref_name }} + BRANCH_NAME: ${{ github.head_ref || github.ref_name }} EXCLUDE_ENTERPRISE: true jobs: ubuntu: runs-on: ubuntu-18.04 - + steps: - uses: actions/checkout@v3 with: @@ -25,16 +25,16 @@ jobs: continue-on-error: true with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" ref: ${{ env.BRANCH_NAME }} - uses: actions/checkout@v3 if: steps.mattermostServer.outcome == 'failure' with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" - ref : "master" + ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go @@ -101,16 +101,16 @@ jobs: continue-on-error: true with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" ref: ${{ env.BRANCH_NAME }} - uses: actions/checkout@v3 if: steps.mattermostServer.outcome == 'failure' with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" - ref : "master" + ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go @@ -159,16 +159,16 @@ jobs: continue-on-error: true with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" ref: ${{ env.BRANCH_NAME }} - uses: actions/checkout@v3 if: steps.mattermostServer.outcome == 'failure' with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" - ref : "master" + ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go @@ -229,16 +229,16 @@ jobs: continue-on-error: true with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" ref: ${{ env.BRANCH_NAME }} - uses: actions/checkout@v3 if: steps.mattermostServer.outcome == 'failure' with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" - ref : "master" + ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go diff --git a/.github/workflows/lint-server.yml b/.github/workflows/lint-server.yml index 3c114e71b..5067a91f0 100644 --- a/.github/workflows/lint-server.yml +++ b/.github/workflows/lint-server.yml @@ -48,7 +48,7 @@ jobs: repository: "mattermost/mattermost-server" fetch-depth: "20" path: "mattermost-server" - ref : "master" + ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: set up golangci-lint run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.50.1 - name: lint diff --git a/.github/workflows/prod-release.yml b/.github/workflows/prod-release.yml index 8ca6f4f98..051234c4a 100644 --- a/.github/workflows/prod-release.yml +++ b/.github/workflows/prod-release.yml @@ -21,16 +21,16 @@ jobs: continue-on-error: true with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" ref: ${{ env.BRANCH_NAME }} - uses: actions/checkout@v3 if: steps.mattermostServer.outcome == 'failure' with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" - ref : "master" + ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go @@ -97,16 +97,16 @@ jobs: continue-on-error: true with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" ref: ${{ env.BRANCH_NAME }} - uses: actions/checkout@v3 if: steps.mattermostServer.outcome == 'failure' with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" - ref : "master" + ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go @@ -156,16 +156,16 @@ jobs: continue-on-error: true with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" ref: ${{ env.BRANCH_NAME }} - uses: actions/checkout@v3 if: steps.mattermostServer.outcome == 'failure' with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" - ref : "master" + ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go @@ -228,16 +228,16 @@ jobs: continue-on-error: true with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" ref: ${{ env.BRANCH_NAME }} - uses: actions/checkout@v3 if: steps.mattermostServer.outcome == 'failure' with: repository: "mattermost/mattermost-server" - fetch-depth: "20" + fetch-depth: "20" path: "mattermost-server" - ref : "master" + ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go From 01b58cb45ac8d234f41fddd0733b4aa1d9788abd Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Wed, 29 Mar 2023 04:13:18 -0600 Subject: [PATCH 039/102] update ubuntu to latest (#4671) --- .github/workflows/ci.yml | 4 ++-- .github/workflows/dev-release.yml | 5 ++--- .github/workflows/lint-server.yml | 4 ++-- .github/workflows/prod-release.yml | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1e15579f3..93155b4a1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ env: jobs: ci-ubuntu-server: - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest strategy: matrix: @@ -54,7 +54,7 @@ jobs: run: cd focalboard; make server-test-${{matrix['db']}} ci-ubuntu-webapp: - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 diff --git a/.github/workflows/dev-release.yml b/.github/workflows/dev-release.yml index e3ad2ed85..da022b71f 100644 --- a/.github/workflows/dev-release.yml +++ b/.github/workflows/dev-release.yml @@ -14,8 +14,7 @@ env: jobs: ubuntu: - runs-on: ubuntu-18.04 - + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: @@ -218,7 +217,7 @@ jobs: path: ${{ github.workspace }}/focalboard/win-wpf/dist/focalboard-win.zip plugin: - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/lint-server.yml b/.github/workflows/lint-server.yml index 5067a91f0..3e505f1cd 100644 --- a/.github/workflows/lint-server.yml +++ b/.github/workflows/lint-server.yml @@ -13,7 +13,7 @@ env: jobs: down-migrations: - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: @@ -26,7 +26,7 @@ jobs: golangci: name: plugin - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - uses: actions/setup-go@v3 with: diff --git a/.github/workflows/prod-release.yml b/.github/workflows/prod-release.yml index 051234c4a..781843a68 100644 --- a/.github/workflows/prod-release.yml +++ b/.github/workflows/prod-release.yml @@ -9,7 +9,7 @@ env: jobs: ubuntu: - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - name: Checkout @@ -216,7 +216,7 @@ jobs: path: ${{ github.workspace }}/focalboard/win-wpf/dist/focalboard-win.zip plugin-release: - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - name: Checkout From 0192ef6f3f51dbebb4e212c24ae6e5fb2423f11d Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Wed, 29 Mar 2023 16:27:18 -0600 Subject: [PATCH 040/102] only send category updates to user (#4672) * only send category updates to user * remove unused function * Revert "remove unused function" This reverts commit 8c4fc9b2002635ea13c73cde31fb32845eca8cb2. * remove unused function * fix test --------- Co-authored-by: Mattermost Build --- server/ws/server.go | 64 +++++++++++++++------------------------- server/ws/server_test.go | 42 ++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 40 deletions(-) diff --git a/server/ws/server.go b/server/ws/server.go index 9df1b1f6e..dfa4af8a1 100644 --- a/server/ws/server.go +++ b/server/ws/server.go @@ -465,10 +465,15 @@ func (ws *Server) getListenersForBlock(blockID string) []*websocketSession { return ws.listenersByBlock[blockID] } -// getListenersForTeam returns the listeners subscribed to a +// getListenersForUser returns the listener for a user subscribed to a // team changes. -func (ws *Server) getListenersForTeam(teamID string) []*websocketSession { - return ws.listenersByTeam[teamID] +func (ws *Server) getListenerForUser(teamID, userID string) *websocketSession { + for _, listener := range ws.listenersByTeam[teamID] { + if listener.userID == userID { + return listener + } + } + return nil } // getListenersForTeamAndBoard returns the listeners subscribed to a @@ -567,16 +572,10 @@ func (ws *Server) BroadcastCategoryChange(category model.Category) { Category: &category, } - listeners := ws.getListenersForTeam(category.TeamID) - ws.logger.Debug("listener(s) for teamID", - mlog.Int("listener_count", len(listeners)), - mlog.String("teamID", category.TeamID), - mlog.String("categoryID", category.ID), - ) - - for _, listener := range listeners { - ws.logger.Debug("Broadcast block change", - mlog.Int("listener_count", len(listeners)), + listener := ws.getListenerForUser(category.TeamID, category.UserID) + if listener != nil { + ws.logger.Debug("Broadcast category change", + mlog.String("userID", category.UserID), mlog.String("teamID", category.TeamID), mlog.String("categoryID", category.ID), mlog.Stringer("remoteAddr", listener.conn.RemoteAddr()), @@ -596,15 +595,10 @@ func (ws *Server) BroadcastCategoryReorder(teamID, userID string, categoryOrder TeamID: teamID, } - listeners := ws.getListenersForTeam(teamID) - ws.logger.Debug("listener(s) for teamID", - mlog.Int("listener_count", len(listeners)), - mlog.String("teamID", teamID), - ) - - for _, listener := range listeners { + listener := ws.getListenerForUser(teamID, userID) + if listener != nil { ws.logger.Debug("Broadcast category order change", - mlog.Int("listener_count", len(listeners)), + mlog.String("userID", userID), mlog.String("teamID", teamID), mlog.Stringer("remoteAddr", listener.conn.RemoteAddr()), ) @@ -624,21 +618,17 @@ func (ws *Server) BroadcastCategoryBoardsReorder(teamID, userID, categoryID stri TeamID: teamID, } - listeners := ws.getListenersForTeam(teamID) - ws.logger.Debug("listener(s) for teamID", - mlog.Int("listener_count", len(listeners)), - mlog.String("teamID", teamID), - ) - - for _, listener := range listeners { + listener := ws.getListenerForUser(teamID, userID) + if listener != nil { ws.logger.Debug("Broadcast board category order change", - mlog.Int("listener_count", len(listeners)), + mlog.String("userID", userID), mlog.String("teamID", teamID), + mlog.String("categoryID", categoryID), mlog.Stringer("remoteAddr", listener.conn.RemoteAddr()), ) if err := listener.WriteJSON(message); err != nil { - ws.logger.Error("broadcast category order change error", mlog.Err(err)) + ws.logger.Error("broadcast category boards order change error", mlog.Err(err)) listener.conn.Close() } } @@ -651,16 +641,10 @@ func (ws *Server) BroadcastCategoryBoardChange(teamID, userID string, boardCateg BoardCategories: boardCategories, } - listeners := ws.getListenersForTeam(teamID) - ws.logger.Debug("listener(s) for teamID", - mlog.Int("listener_count", len(listeners)), - mlog.String("teamID", teamID), - mlog.Int("numEntries", len(boardCategories)), - ) - - for _, listener := range listeners { - ws.logger.Debug("Broadcast block change", - mlog.Int("listener_count", len(listeners)), + listener := ws.getListenerForUser(teamID, userID) + if listener != nil { + ws.logger.Debug("Broadcast category board change", + mlog.String("userID", userID), mlog.String("teamID", teamID), mlog.Int("numEntries", len(boardCategories)), mlog.Stringer("remoteAddr", listener.conn.RemoteAddr()), diff --git a/server/ws/server_test.go b/server/ws/server_test.go index ba56bacc1..fa728e2cd 100644 --- a/server/ws/server_test.go +++ b/server/ws/server_test.go @@ -101,6 +101,48 @@ func TestTeamSubscription(t *testing.T) { require.Empty(t, server.listenersByTeam[teamID]) require.Empty(t, server.listenersByTeam[teamID2]) }) + + t.Run("Subscribe users to team retrieve by user", func(t *testing.T) { + userID1 := "fake-user-id" + userSession1 := &websocketSession{ + conn: &websocket.Conn{}, + mu: sync.Mutex{}, + userID: userID1, + teams: []string{}, + blocks: []string{}, + } + userID2 := "fake-user-id2" + userSession2 := &websocketSession{ + conn: &websocket.Conn{}, + mu: sync.Mutex{}, + userID: userID2, + teams: []string{}, + blocks: []string{}, + } + teamID := "fake-team-id" + + server.addListener(session) + server.subscribeListenerToTeam(session, teamID) + server.addListener(userSession1) + server.subscribeListenerToTeam(userSession1, teamID) + server.addListener(userSession2) + server.subscribeListenerToTeam(userSession2, teamID) + + require.Len(t, server.listeners, 3) + require.Len(t, server.listenersByTeam[teamID], 3) + + listener := server.getListenerForUser(teamID, userID1) + require.NotNil(t, listener) + require.Equal(t, listener.userID, userID1) + + server.removeListener(session) + server.removeListener(userSession1) + server.removeListener(userSession2) + + require.Empty(t, server.listeners) + require.Empty(t, server.listenersByTeam[teamID]) + require.Empty(t, server.getListenerForUser(teamID, userID1)) + }) } func TestBlocksSubscription(t *testing.T) { From 263492415037606da1c59250306a50b487f1517d Mon Sep 17 00:00:00 2001 From: Harshil Sharma <18575143+harshilsharma63@users.noreply.github.com> Date: Thu, 30 Mar 2023 14:20:50 +0530 Subject: [PATCH 041/102] Cherrypicking 22606 to old focalboard (#4673) --- .../store/sqlstore/data_migrations.go | 6 ++-- .../migrationstests/boards_migrator_test.go | 3 ++ ...uplicate_category_boards_migration_test.go | 28 +++++++++++++++++++ .../fixtures/test33_with_deleted_data.sql | 6 ++-- .../fixtures/test33_with_no_deleted_data.sql | 6 ++-- .../fixtures/test37_valid_data.sql | 6 ++-- .../test37_valid_data_no_hidden_boards.sql | 6 ++-- ...id_data_preference_but_no_hidden_board.sql | 6 ++-- .../fixtures/test37_valid_data_sqlite.sql | 6 ++-- ..._sqlite_preference_but_no_hidden_board.sql | 6 ++-- ...testDeDuplicateCategoryBoardsMigration.sql | 9 ++++++ 11 files changed, 70 insertions(+), 18 deletions(-) create mode 100644 server/services/store/sqlstore/migrationstests/de_duplicate_category_boards_migration_test.go create mode 100644 server/services/store/sqlstore/migrationstests/fixtures/testDeDuplicateCategoryBoardsMigration.sql diff --git a/server/services/store/sqlstore/data_migrations.go b/server/services/store/sqlstore/data_migrations.go index bbc7e2218..1794965ca 100644 --- a/server/services/store/sqlstore/data_migrations.go +++ b/server/services/store/sqlstore/data_migrations.go @@ -868,10 +868,8 @@ func (s *SQLStore) doesDuplicateCategoryBoardsExist() (bool, error) { } func (s *SQLStore) runMySQLDeDuplicateCategoryBoardsMigration() error { - query := "WITH duplicates AS (SELECT id, ROW_NUMBER() OVER(PARTITION BY user_id, board_id) AS rownum " + - "FROM " + s.tablePrefix + "category_boards) " + - "DELETE " + s.tablePrefix + "category_boards FROM " + s.tablePrefix + "category_boards " + - "JOIN duplicates USING(id) WHERE duplicates.rownum > 1;" + query := "DELETE FROM " + s.tablePrefix + "category_boards WHERE id NOT IN " + + "(SELECT * FROM ( SELECT min(id) FROM " + s.tablePrefix + "category_boards GROUP BY user_id, board_id ) as data)" if _, err := s.db.Exec(query); err != nil { s.logger.Error("Failed to de-duplicate data in category_boards table", mlog.Err(err)) } diff --git a/server/services/store/sqlstore/migrationstests/boards_migrator_test.go b/server/services/store/sqlstore/migrationstests/boards_migrator_test.go index 9ec8ea3b2..2808d96fa 100644 --- a/server/services/store/sqlstore/migrationstests/boards_migrator_test.go +++ b/server/services/store/sqlstore/migrationstests/boards_migrator_test.go @@ -246,6 +246,9 @@ func (bm *BoardsMigrator) MigrateToStep(step int) error { func (bm *BoardsMigrator) Interceptors() map[int]foundation.Interceptor { return map[int]foundation.Interceptor{ 18: bm.store.RunDeletedMembershipBoardsMigration, + 35: func() error { + return bm.store.RunDeDuplicateCategoryBoardsMigration(35) + }, } } diff --git a/server/services/store/sqlstore/migrationstests/de_duplicate_category_boards_migration_test.go b/server/services/store/sqlstore/migrationstests/de_duplicate_category_boards_migration_test.go new file mode 100644 index 000000000..863cb43ff --- /dev/null +++ b/server/services/store/sqlstore/migrationstests/de_duplicate_category_boards_migration_test.go @@ -0,0 +1,28 @@ +package migrationstests + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestRunDeDuplicateCategoryBoardsMigration(t *testing.T) { + th, tearDown := SetupTestHelper(t) + defer tearDown() + + if th.IsSQLite() { + t.Skip("SQLite is not supported for this") + } + + th.f.MigrateToStepSkippingLastInterceptor(35). + ExecFile("./fixtures/testDeDuplicateCategoryBoardsMigration.sql") + + th.f.RunInterceptor(35) + + // verifying count of rows + var count int + countQuery := "SELECT COUNT(*) FROM focalboard_category_boards" + row := th.f.DB().QueryRow(countQuery) + err := row.Scan(&count) + assert.NoError(t, err) + assert.Equal(t, 4, count) +} diff --git a/server/services/store/sqlstore/migrationstests/fixtures/test33_with_deleted_data.sql b/server/services/store/sqlstore/migrationstests/fixtures/test33_with_deleted_data.sql index c5593660b..f9e0b1a73 100644 --- a/server/services/store/sqlstore/migrationstests/fixtures/test33_with_deleted_data.sql +++ b/server/services/store/sqlstore/migrationstests/fixtures/test33_with_deleted_data.sql @@ -1,6 +1,8 @@ -INSERT INTO focalboard_category_boards values +INSERT INTO focalboard_category_boards +(id, user_id, category_id, board_id, create_at, update_at, delete_at, sort_order) +values ('id-1', 'user_id-1', 'category-id-1', 'board-id-1', 1672988834402, 1672988834402, 0, 0), ('id-2', 'user_id-1', 'category-id-2', 'board-id-1', 1672988834402, 1672988834402, 0, 0), ('id-3', 'user_id-2', 'category-id-3', 'board-id-2', 1672988834402, 1672988834402, 1672988834402, 0), ('id-4', 'user_id-2', 'category-id-3', 'board-id-4', 1672988834402, 1672988834402, 0, 0), -('id-5', 'user_id-3', 'category-id-4', 'board-id-3', 1672988834402, 1672988834402, 1672988834402, 0); \ No newline at end of file +('id-5', 'user_id-3', 'category-id-4', 'board-id-3', 1672988834402, 1672988834402, 1672988834402, 0); diff --git a/server/services/store/sqlstore/migrationstests/fixtures/test33_with_no_deleted_data.sql b/server/services/store/sqlstore/migrationstests/fixtures/test33_with_no_deleted_data.sql index 5f4337bb2..5bc32a714 100644 --- a/server/services/store/sqlstore/migrationstests/fixtures/test33_with_no_deleted_data.sql +++ b/server/services/store/sqlstore/migrationstests/fixtures/test33_with_no_deleted_data.sql @@ -1,6 +1,8 @@ -INSERT INTO focalboard_category_boards values +INSERT INTO focalboard_category_boards +(id, user_id, category_id, board_id, create_at, update_at, delete_at, sort_order) +values ('id-1', 'user_id-1', 'category-id-1', 'board-id-1', 1672988834402, 1672988834402, 0, 0), ('id-2', 'user_id-1', 'category-id-2', 'board-id-1', 1672988834402, 1672988834402, 0, 0), ('id-3', 'user_id-2', 'category-id-3', 'board-id-2', 1672988834402, 1672988834402, 0, 0), ('id-4', 'user_id-2', 'category-id-3', 'board-id-4', 1672988834402, 1672988834402, 0, 0), -('id-5', 'user_id-3', 'category-id-4', 'board-id-3', 1672988834402, 1672988834402, 0, 0); \ No newline at end of file +('id-5', 'user_id-3', 'category-id-4', 'board-id-3', 1672988834402, 1672988834402, 0, 0); diff --git a/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data.sql b/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data.sql index 8f75da315..552703ec6 100644 --- a/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data.sql +++ b/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data.sql @@ -1,4 +1,6 @@ -INSERT INTO focalboard_category_boards VALUES +INSERT INTO focalboard_category_boards +(id, user_id, category_id, board_id, create_at, update_at, sort_order, hidden) +VALUES ('id-1', 'user-id-1', 'category-id-1', 'board-id-1', 1672889246832, 1672889246832, 0, false), ('id-2', 'user-id-1', 'category-id-2', 'board-id-2', 1672889246832, 1672889246832, 0, false), ('id-3', 'user-id-2', 'category-id-3', 'board-id-3', 1672889246832, 1672889246832, 0, false), @@ -7,4 +9,4 @@ INSERT INTO focalboard_category_boards VALUES INSERT INTO Preferences VALUES ('user-id-1', 'focalboard', 'hiddenBoardIDs', '["board-id-1"]'), -('user-id-2', 'focalboard', 'hiddenBoardIDs', '["board-id-3", "board-id-4"]'); \ No newline at end of file +('user-id-2', 'focalboard', 'hiddenBoardIDs', '["board-id-3", "board-id-4"]'); diff --git a/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_no_hidden_boards.sql b/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_no_hidden_boards.sql index 2986bad28..3b6508f5c 100644 --- a/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_no_hidden_boards.sql +++ b/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_no_hidden_boards.sql @@ -1,6 +1,8 @@ -INSERT INTO focalboard_category_boards VALUES +INSERT INTO focalboard_category_boards +(id, user_id, category_id, board_id, create_at, update_at, sort_order, hidden) +VALUES ('id-1', 'user-id-1', 'category-id-1', 'board-id-1', 1672889246832, 1672889246832, 0, false), ('id-2', 'user-id-1', 'category-id-2', 'board-id-2', 1672889246832, 1672889246832, 0, false), ('id-3', 'user-id-2', 'category-id-3', 'board-id-3', 1672889246832, 1672889246832, 0, false), ('id-4', 'user-id-2', 'category-id-3', 'board-id-4', 1672889246832, 1672889246832, 0, false), -('id-5', 'user-id-3', 'category-id-4', 'board-id-5', 1672889246832, 1672889246832, 0, false); \ No newline at end of file +('id-5', 'user-id-3', 'category-id-4', 'board-id-5', 1672889246832, 1672889246832, 0, false); diff --git a/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_preference_but_no_hidden_board.sql b/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_preference_but_no_hidden_board.sql index 943932e54..75e127332 100644 --- a/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_preference_but_no_hidden_board.sql +++ b/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_preference_but_no_hidden_board.sql @@ -1,4 +1,6 @@ -INSERT INTO focalboard_category_boards VALUES +INSERT INTO focalboard_category_boards +(id, user_id, category_id, board_id, create_at, update_at, sort_order, hidden) +VALUES ('id-1', 'user-id-1', 'category-id-1', 'board-id-1', 1672889246832, 1672889246832, 0, false), ('id-2', 'user-id-1', 'category-id-2', 'board-id-2', 1672889246832, 1672889246832, 0, false), ('id-3', 'user-id-2', 'category-id-3', 'board-id-3', 1672889246832, 1672889246832, 0, false), @@ -7,4 +9,4 @@ INSERT INTO focalboard_category_boards VALUES INSERT INTO Preferences VALUES ('user-id-1', 'focalboard', 'hiddenBoardIDs', ''), -('user-id-2', 'focalboard', 'hiddenBoardIDs', ''); \ No newline at end of file +('user-id-2', 'focalboard', 'hiddenBoardIDs', ''); diff --git a/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_sqlite.sql b/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_sqlite.sql index 114273c30..deb74ccaf 100644 --- a/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_sqlite.sql +++ b/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_sqlite.sql @@ -1,4 +1,6 @@ -INSERT INTO focalboard_category_boards VALUES +INSERT INTO focalboard_category_boards +(id, user_id, category_id, board_id, create_at, update_at, sort_order, hidden) +VALUES ('id-1', 'user-id-1', 'category-id-1', 'board-id-1', 1672889246832, 1672889246832, 0, false), ('id-2', 'user-id-1', 'category-id-2', 'board-id-2', 1672889246832, 1672889246832, 0, false), ('id-3', 'user-id-2', 'category-id-3', 'board-id-3', 1672889246832, 1672889246832, 0, false), @@ -7,4 +9,4 @@ INSERT INTO focalboard_category_boards VALUES INSERT INTO focalboard_preferences VALUES ('user-id-1', 'focalboard', 'hiddenBoardIDs', '["board-id-1"]'), -('user-id-2', 'focalboard', 'hiddenBoardIDs', '["board-id-3", "board-id-4"]'); \ No newline at end of file +('user-id-2', 'focalboard', 'hiddenBoardIDs', '["board-id-3", "board-id-4"]'); diff --git a/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_sqlite_preference_but_no_hidden_board.sql b/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_sqlite_preference_but_no_hidden_board.sql index 4b45cacdf..62dc2b708 100644 --- a/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_sqlite_preference_but_no_hidden_board.sql +++ b/server/services/store/sqlstore/migrationstests/fixtures/test37_valid_data_sqlite_preference_but_no_hidden_board.sql @@ -1,4 +1,6 @@ -INSERT INTO focalboard_category_boards VALUES +INSERT INTO focalboard_category_boards +(id, user_id, category_id, board_id, create_at, update_at, sort_order, hidden) +VALUES ('id-1', 'user-id-1', 'category-id-1', 'board-id-1', 1672889246832, 1672889246832, 0, false), ('id-2', 'user-id-1', 'category-id-2', 'board-id-2', 1672889246832, 1672889246832, 0, false), ('id-3', 'user-id-2', 'category-id-3', 'board-id-3', 1672889246832, 1672889246832, 0, false), @@ -7,4 +9,4 @@ INSERT INTO focalboard_category_boards VALUES INSERT INTO focalboard_preferences VALUES ('user-id-1', 'focalboard', 'hiddenBoardIDs', ''), -('user-id-2', 'focalboard', 'hiddenBoardIDs', ''); \ No newline at end of file +('user-id-2', 'focalboard', 'hiddenBoardIDs', ''); diff --git a/server/services/store/sqlstore/migrationstests/fixtures/testDeDuplicateCategoryBoardsMigration.sql b/server/services/store/sqlstore/migrationstests/fixtures/testDeDuplicateCategoryBoardsMigration.sql new file mode 100644 index 000000000..69a7dc9bd --- /dev/null +++ b/server/services/store/sqlstore/migrationstests/fixtures/testDeDuplicateCategoryBoardsMigration.sql @@ -0,0 +1,9 @@ +INSERT INTO focalboard_category_boards(id, user_id, category_id, board_id, create_at, update_at, sort_order) +VALUES + ('id_1', 'user_id_1', 'category_id_1', 'board_id_1', 0, 0, 0), + ('id_2', 'user_id_1', 'category_id_2', 'board_id_1', 0, 0, 0), + ('id_3', 'user_id_1', 'category_id_3', 'board_id_1', 0, 0, 0), + ('id_4', 'user_id_2', 'category_id_4', 'board_id_2', 0, 0, 0), + ('id_5', 'user_id_2', 'category_id_5', 'board_id_2', 0, 0, 0), + ('id_6', 'user_id_3', 'category_id_6', 'board_id_3', 0, 0, 0), + ('id_7', 'user_id_4', 'category_id_6', 'board_id_4', 0, 0, 0); From 13c33acb7da5910c371262e9b4a18a498ad08b6a Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Thu, 30 Mar 2023 03:45:32 -0600 Subject: [PATCH 042/102] MM-51795 Remove free cloud server message (#4677) * remove free cloud server message * remove selector for cloud message * remove unused import --- webapp/i18n/en.json | 14 +- .../__snapshots__/cloudMessage.test.tsx.snap | 73 ------- .../src/components/messages/cloudMessage.scss | 38 ---- .../components/messages/cloudMessage.test.tsx | 190 ------------------ .../src/components/messages/cloudMessage.tsx | 114 ----------- .../components/messages/versionMessage.tsx | 2 +- webapp/src/pages/boardPage/boardPage.scss | 1 - webapp/src/pages/boardPage/boardPage.tsx | 2 - webapp/src/store/users.ts | 18 -- webapp/src/userSettings.ts | 9 - 10 files changed, 13 insertions(+), 448 deletions(-) delete mode 100644 webapp/src/components/messages/__snapshots__/cloudMessage.test.tsx.snap delete mode 100644 webapp/src/components/messages/cloudMessage.scss delete mode 100644 webapp/src/components/messages/cloudMessage.test.tsx delete mode 100644 webapp/src/components/messages/cloudMessage.tsx diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json index b7a90daf5..6dd6746d6 100644 --- a/webapp/i18n/en.json +++ b/webapp/i18n/en.json @@ -1,5 +1,7 @@ { - "AppBar.Tooltip": "Toggle linked boards", + "AdminBadge.SystemAdmin": "Admin", + "AdminBadge.TeamAdmin": "Team Admin", + "AppBar.Tooltip": "Toggle Linked Boards", "Attachment.Attachment-title": "Attachment", "AttachmentBlock.DeleteAction": "delete", "AttachmentBlock.addElement": "add {type}", @@ -115,7 +117,6 @@ "CenterPanel.Login": "Login", "CenterPanel.Share": "Share", "ChannelIntro.CreateBoard": "Create a board", - "CloudMessage.cloud-server": "Get your own free cloud server.", "ColorOption.selectColor": "Select {color} Color", "Comment.delete": "Delete", "CommentsList.send": "Send", @@ -138,6 +139,7 @@ "ContentBlock.moveDown": "Move down", "ContentBlock.moveUp": "Move up", "ContentBlock.text": "text", + "DateFilter.empty": "Empty", "DateRange.clear": "Clear", "DateRange.empty": "Empty", "DateRange.endDate": "End date", @@ -156,10 +158,14 @@ "Filter.ends-with": "ends with", "Filter.includes": "includes", "Filter.is": "is", + "Filter.is-after": "is after", + "Filter.is-before": "is before", "Filter.is-empty": "is empty", "Filter.is-not-empty": "is not empty", "Filter.is-not-set": "is not set", "Filter.is-set": "is set", + "Filter.isafter": "is after", + "Filter.isbefore": "is before", "Filter.not-contains": "doesn't contain", "Filter.not-ends-with": "doesn't end with", "Filter.not-includes": "doesn't include", @@ -306,6 +312,7 @@ "ValueSelector.valueSelector": "Value selector", "ValueSelectorLabel.openMenu": "Open menu", "VersionMessage.help": "Check out what's new in this version.", + "VersionMessage.learn-more": "Learn more", "View.AddView": "Add view", "View.Board": "Board", "View.DeleteView": "Delete view", @@ -360,6 +367,9 @@ "WelcomePage.StartUsingIt.Text": "Start using it", "Workspace.editing-board-template": "You're editing a board template.", "badge.guest": "Guest", + "boardPage.confirm-join-button": "Join", + "boardPage.confirm-join-text": "You are about to join a private board without explicitly being added by the board admin. Are you sure you wish to join this private board?", + "boardPage.confirm-join-title": "Join private board", "boardSelector.confirm-link-board": "Link board to channel", "boardSelector.confirm-link-board-button": "Yes, link board", "boardSelector.confirm-link-board-subtext": "When you link \"{boardName}\" to the channel, all members of the channel (existing and new) will be able to edit it. This excludes members who are guests. You can unlink a board from a channel at any time.", diff --git a/webapp/src/components/messages/__snapshots__/cloudMessage.test.tsx.snap b/webapp/src/components/messages/__snapshots__/cloudMessage.test.tsx.snap deleted file mode 100644 index 66a121574..000000000 --- a/webapp/src/components/messages/__snapshots__/cloudMessage.test.tsx.snap +++ /dev/null @@ -1,73 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`components/messages/CloudMessage not plugin mode, close message 1`] = `
`; - -exports[`components/messages/CloudMessage not plugin mode, show message, close message 1`] = ` -
-
- - -
-
-`; - -exports[`components/messages/CloudMessage not plugin mode, single user, close message 1`] = ` -
-
- - -
-
-`; - -exports[`components/messages/CloudMessage plugin mode, no display 1`] = `
`; diff --git a/webapp/src/components/messages/cloudMessage.scss b/webapp/src/components/messages/cloudMessage.scss deleted file mode 100644 index f6c86bba5..000000000 --- a/webapp/src/components/messages/cloudMessage.scss +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. -.CloudMessage { - background-color: rgb(var(--sidebar-text-active-border-rgb)); - display: flex; - flex-direction: row; - align-items: center; - text-align: center; - font-weight: 600; - - div { - width: 100%; - } - - > .banner { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - padding: 10px; - color: #fff; - - .CompassIcon { - font-size: 18px; - margin-right: 2px; - } - - .Button { - margin-left: 8px; - background-color: rgba(255, 255, 255, 0.16); - } - } - - .IconButton { - float: right; - color: #fff; - } -} diff --git a/webapp/src/components/messages/cloudMessage.test.tsx b/webapp/src/components/messages/cloudMessage.test.tsx deleted file mode 100644 index cd399ede4..000000000 --- a/webapp/src/components/messages/cloudMessage.test.tsx +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React from 'react' -import {Provider as ReduxProvider} from 'react-redux' - -import {render, screen} from '@testing-library/react' -import {mocked} from 'jest-mock' -import userEvent from '@testing-library/user-event' - -import configureStore from 'redux-mock-store' - -import {Utils} from '../../utils' - -import {IUser} from '../../user' - -import {wrapIntl} from '../../testUtils' - -import client from '../../octoClient' - -import {UserSettings} from '../../userSettings' - -import CloudMessage from './cloudMessage' - -jest.mock('../../utils') -jest.mock('../../octoClient') -const mockedOctoClient = mocked(client, true) - -describe('components/messages/CloudMessage', () => { - beforeEach(() => { - jest.clearAllMocks() - }) - - const mockedUtils = mocked(Utils, true) - const mockStore = configureStore([]) - - test('plugin mode, no display', () => { - mockedUtils.isFocalboardPlugin.mockReturnValue(true) - - const me: IUser = { - id: 'user-id-1', - username: 'username_1', - email: '', - nickname: '', - firstname: '', - lastname: '', - props: {}, - create_at: 0, - update_at: 0, - is_bot: false, - is_guest: false, - roles: 'system_user', - } - const state = { - users: { - me, - }, - } - - const store = mockStore(state) - - const component = wrapIntl( - - - , - ) - - const {container} = render(component) - expect(container).toMatchSnapshot() - }) - - test('not plugin mode, close message', () => { - const me: IUser = { - id: 'user-id-1', - username: 'username_1', - email: '', - nickname: '', - firstname: '', - lastname: '', - create_at: 0, - update_at: 0, - is_bot: false, - is_guest: false, - roles: 'system_user', - props: {}, - } - const state = { - users: { - me, - myConfig: { - cloudMessageCanceled: {value: 'true'}, - }, - }, - } - const store = mockStore(state) - mockedUtils.isFocalboardPlugin.mockReturnValue(false) - - const component = wrapIntl( - - - , - ) - - const {container} = render(component) - expect(container).toMatchSnapshot() - }) - - test('not plugin mode, show message, close message', () => { - const me: IUser = { - id: 'user-id-1', - username: 'username_1', - email: '', - nickname: '', - firstname: '', - lastname: '', - props: {}, - create_at: 0, - update_at: 0, - is_bot: false, - is_guest: false, - roles: 'system_user', - } - const state = { - users: { - me, - }, - } - const store = mockStore(state) - mockedUtils.isFocalboardPlugin.mockReturnValue(false) - - const component = wrapIntl( - - - , - ) - - const {container} = render(component) - expect(container).toMatchSnapshot() - - const buttonElement = screen.getByRole('button', {name: 'Close dialog'}) - userEvent.click(buttonElement) - expect(mockedOctoClient.patchUserConfig).toBeCalledWith('user-id-1', { - updatedFields: { - cloudMessageCanceled: 'true', - }, - }) - }) - - test('not plugin mode, single user, close message', () => { - const me: IUser = { - id: 'single-user', - username: 'single-user', - email: 'single-user', - nickname: '', - firstname: '', - lastname: '', - props: {}, - create_at: 0, - update_at: Date.now() - (1000 * 60 * 60 * 24), //24 hours, - is_bot: false, - is_guest: false, - roles: 'system_user', - } - const state = { - users: { - me, - }, - } - const store = mockStore(state) - const hideCloudMessageSpy = jest.spyOn(UserSettings, 'hideCloudMessage', 'set') - - mockedUtils.isFocalboardPlugin.mockReturnValue(false) - - const component = wrapIntl( - - - , - ) - - const {container} = render(component) - expect(container).toMatchSnapshot() - - const buttonElement = screen.getByRole('button', {name: 'Close dialog'}) - userEvent.click(buttonElement) - - expect(mockedOctoClient.patchUserConfig).toBeCalledTimes(0) - expect(hideCloudMessageSpy).toHaveBeenCalledWith(true) - expect(UserSettings.hideCloudMessage).toBe(true) - }) -}) diff --git a/webapp/src/components/messages/cloudMessage.tsx b/webapp/src/components/messages/cloudMessage.tsx deleted file mode 100644 index a35bd8e65..000000000 --- a/webapp/src/components/messages/cloudMessage.tsx +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. -import React from 'react' - -import {useIntl, FormattedMessage} from 'react-intl' - -import {Utils} from '../../utils' -import IconButton from '../../widgets/buttons/iconButton' -import Button from '../../widgets/buttons/button' - -import CloseIcon from '../../widgets/icons/close' - -import {useAppSelector, useAppDispatch} from '../../store/hooks' -import octoClient from '../../octoClient' -import {IUser, UserConfigPatch} from '../../user' -import {getMe, patchProps, getCloudMessageCanceled} from '../../store/users' -import {UserSettings} from '../../userSettings' - -import CompassIcon from '../../widgets/icons/compassIcon' -import TelemetryClient, {TelemetryCategory, TelemetryActions} from '../../telemetry/telemetryClient' - -import './cloudMessage.scss' -const signupURL = 'https://mattermost.com/pricing' -const displayAfter = (1000 * 60 * 60 * 24) //24 hours - -const CloudMessage = React.memo(() => { - const intl = useIntl() - const dispatch = useAppDispatch() - const me = useAppSelector(getMe) - const cloudMessageCanceled = useAppSelector(getCloudMessageCanceled) - - const closeDialogText = intl.formatMessage({ - id: 'Dialog.closeDialog', - defaultMessage: 'Close dialog', - }) - - const onClose = async () => { - if (me) { - if (me.id === 'single-user') { - UserSettings.hideCloudMessage = true - dispatch(patchProps([ - { - user_id: me.id, - category: 'focalboard', - name: 'cloudMessageCanceled', - value: 'true', - }, - ])) - return - } - const patch: UserConfigPatch = { - updatedFields: { - cloudMessageCanceled: 'true', - }, - } - - const patchedProps = await octoClient.patchUserConfig(me.id, patch) - if (patchedProps) { - dispatch(patchProps(patchedProps)) - } - } - } - - if (Utils.isFocalboardPlugin() || cloudMessageCanceled) { - return null - } - - if (me) { - const installTime = Date.now() - me.create_at - if (installTime < displayAfter) { - return null - } - } - - return ( -
-
- - - - - -
- - } - title={closeDialogText} - size='small' - /> -
- ) -}) -export default CloudMessage diff --git a/webapp/src/components/messages/versionMessage.tsx b/webapp/src/components/messages/versionMessage.tsx index 1c21d27f1..e08791df2 100644 --- a/webapp/src/components/messages/versionMessage.tsx +++ b/webapp/src/components/messages/versionMessage.tsx @@ -71,7 +71,7 @@ const VersionMessage = React.memo(() => { }} > diff --git a/webapp/src/pages/boardPage/boardPage.scss b/webapp/src/pages/boardPage/boardPage.scss index 7b1a3c4a0..fcf6fe9bc 100644 --- a/webapp/src/pages/boardPage/boardPage.scss +++ b/webapp/src/pages/boardPage/boardPage.scss @@ -1,7 +1,6 @@ .BoardPage { position: relative; - .CloudMessage:not(:first-child), .VersionMessage:not(:first-child) { position: absolute; top: 0; diff --git a/webapp/src/pages/boardPage/boardPage.tsx b/webapp/src/pages/boardPage/boardPage.tsx index 35d9399f5..a2b4e953b 100644 --- a/webapp/src/pages/boardPage/boardPage.tsx +++ b/webapp/src/pages/boardPage/boardPage.tsx @@ -6,7 +6,6 @@ import {FormattedMessage, useIntl} from 'react-intl' import {useRouteMatch, useHistory} from 'react-router-dom' import Workspace from '../../components/workspace' -import CloudMessage from '../../components/messages/cloudMessage' import VersionMessage from '../../components/messages/versionMessage' import octoClient from '../../octoClient' import {Subscription, WSClient} from '../../wsclient' @@ -300,7 +299,6 @@ const BoardPage = (props: Props): JSX.Element => { - {!mobileWarningClosed && diff --git a/webapp/src/store/users.ts b/webapp/src/store/users.ts index 0bb90dec9..cb5a71a0a 100644 --- a/webapp/src/store/users.ts +++ b/webapp/src/store/users.ts @@ -10,10 +10,6 @@ import {Utils} from '../utils' import {Subscription} from '../wsclient' -// TODO: change this whene the initial load is complete -// import {initialLoad} from './initialLoad' -import {UserSettings} from '../userSettings' - import {initialLoad} from './initialLoad' import {RootState} from './index' @@ -169,20 +165,6 @@ export const getOnboardingTourCategory = createSelector( (myConfig): string => (myConfig.tourCategory ? myConfig.tourCategory.value : ''), ) -export const getCloudMessageCanceled = createSelector( - getMe, - getMyConfig, - (me, myConfig): boolean => { - if (!me) { - return false - } - if (me.id === 'single-user') { - return UserSettings.hideCloudMessage - } - return Boolean(myConfig.cloudMessageCanceled?.value) - }, -) - export const getVersionMessageCanceled = createSelector( getMe, getMyConfig, diff --git a/webapp/src/userSettings.ts b/webapp/src/userSettings.ts index 61d02a4a3..3b1fc504a 100644 --- a/webapp/src/userSettings.ts +++ b/webapp/src/userSettings.ts @@ -17,7 +17,6 @@ export enum UserSettingKey { RandomIcons = 'randomIcons', MobileWarningClosed = 'mobileWarningClosed', WelcomePageViewed = 'welcomePageViewed', - HideCloudMessage = 'hideCloudMessage', NameFormat = 'nameFormat' } @@ -149,14 +148,6 @@ export class UserSettings { UserSettings.set(UserSettingKey.MobileWarningClosed, String(newValue)) } - static get hideCloudMessage(): boolean { - return localStorage.getItem(UserSettingKey.HideCloudMessage) === 'true' - } - - static set hideCloudMessage(newValue: boolean) { - localStorage.setItem(UserSettingKey.HideCloudMessage, JSON.stringify(newValue)) - } - static get nameFormat(): string | null { return UserSettings.get(UserSettingKey.NameFormat) } From dfd3d3edfc2fb92ba6af57a6a80ffc2f23a8d76b Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Thu, 30 Mar 2023 10:01:12 -0600 Subject: [PATCH 043/102] need url for emoji picker --- webapp/src/widgets/emojiPicker.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webapp/src/widgets/emojiPicker.tsx b/webapp/src/widgets/emojiPicker.tsx index 147fc1d82..b531445f2 100644 --- a/webapp/src/widgets/emojiPicker.tsx +++ b/webapp/src/widgets/emojiPicker.tsx @@ -5,6 +5,7 @@ import React, {FC} from 'react' import 'emoji-mart/css/emoji-mart.css' import {Picker, BaseEmoji} from 'emoji-mart' +import {Utils} from '../utils' import './emojiPicker.scss' import emojiSpirit from '../../static/emoji_spirit.png' @@ -20,7 +21,7 @@ const EmojiPicker: FC = (props: Props): JSX.Element => ( > props.onSelect(emoji.native)} - backgroundImageFn={() => emojiSpirit} + backgroundImageFn={() => Utils.buildURL(emojiSpirit, true)} />
) From a015aa2cf2cc7db727dd0d8eb707e01c6549ae4d Mon Sep 17 00:00:00 2001 From: Winson Wu <93531870+wuwinson@users.noreply.github.com> Date: Thu, 30 Mar 2023 16:03:45 -0400 Subject: [PATCH 044/102] Update README.md for Focalboard Added details around sunsetting Personal Editions as well as changes to the plugin. --- README.md | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index b75698682..b94073679 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ +# Announcement +Focalboard Personal Server and Personal Desktop editions will transition to being fully community supported as of **April 30th, 2023**. This Focalboard repository will become the Personal Edition repository, and will remain open indefinitely. However, we won’t be adding any new enhancements, and will only address Sev-1 level bugs until April 30th, 2023. + +The Boards plugin version will be integrated into Mattermost as a core in-product feature, and will no longer be supported as a plugin as of release v7.11 (May 2023). The plugin code will be merged into the [Mattermost-server repository](https://github.com/mattermost/mattermost-server) where future enhancements will be added to moving forward. + +Please see [this dicussion](https://github.com/mattermost/focalboard/discussions/4645) for more details. + # Focalboard ![CI Status](https://github.com/mattermost/focalboard/actions/workflows/ci.yml/badge.svg) @@ -10,27 +17,23 @@ Like what you see? :eyes: Give us a GitHub Star! :star: -[![Focalboard](website/site/static/img/hero.jpg)](https://www.focalboard.com) +![Focalboard](website/site/static/img/hero.jpg) -[Focalboard](https://www.focalboard.com) is an open source, multilingual, self-hosted project management tool that's an alternative to Trello, Notion, and Asana. +Focalboard is an open source, multilingual, self-hosted project management tool that's an alternative to Trello, Notion, and Asana. -It helps define, organize, track and manage work across individuals and teams. Focalboard comes in two main editions: +It helps define, organize, track and manage work across individuals and teams. Focalboard comes in three editions: -* **[Mattermost Boards](https://www.focalboard.com/download/mattermost/)**: A self-hosted or **[free cloud server](https://mattermost.com/sign-up/?utm_source=github&utm_campaign=focalboard)** for your team to plan and collaborate. +* **[Mattermost Boards](https://mattermost.com/boards/)**: Integrated with the Mattermost platform for your team to plan and collaborate. -* **[Personal Desktop](https://www.focalboard.com/download/personal-edition/desktop/)**: A standalone, single-user [macOS](https://apps.apple.com/app/apple-store/id1556908618?pt=2114704&ct=website&mt=8), [Windows](https://www.microsoft.com/store/apps/9NLN2T0SX9VF?cid=website), or [Linux](https://www.focalboard.com/download/personal-edition/desktop/#linux-desktop) desktop app for your own todos and personal projects. +* **[Personal Desktop](https://www.focalboard.com/docs/personal-edition/desktop/)**: A standalone, single-user [macOS](https://apps.apple.com/app/apple-store/id1556908618?pt=2114704&ct=website&mt=8), [Windows](https://www.microsoft.com/store/apps/9NLN2T0SX9VF?cid=website), or [Linux](https://www.focalboard.com/download/personal-edition/desktop/#linux-desktop) desktop app for your own todos and personal projects. -Focalboard can also be installed as a standalone **[Personal Server](https://www.focalboard.com/download/personal-edition/ubuntu/)** for development and personal use. +* **[Personal Server](https://www.focalboard.com/download/personal-edition/ubuntu/)**: A standalone, multi-user server for development and personal use. ## Try Focalboard -### Mattermost Boards - [now available as a free cloud server](https://mattermost.com/sign-up/?utm_source=github&utm_campaign=focalboard) +### Mattermost Boards -**Mattermost Boards** combines project management tools with messaging and collaboration for teams of all sizes. To access and use **Mattermost Boards**, install or upgrade to Mattermost v6.0 or later as a [self-hosted server](https://docs.mattermost.com/guides/deployment.html?utm_source=github&utm_campaign=focalboard) or [Cloud server](https://mattermost.com/sign-up/?utm_source=github&utm_campaign=focalboard). After logging into Mattermost, select the menu in the top left corner and select **Boards**. - -***Mattermost Boards** is installed and enabled by default in Mattermost v6.0 and later.* - -See the [plugin setup guide](https://www.focalboard.com/download/mattermost/) for more details. +**Mattermost Boards** combines project management tools with messaging and collaboration for teams of all sizes. To access and use **Mattermost Boards**, install or upgrade to Mattermost v6.0 or later as a [self-hosted server](https://docs.mattermost.com/guides/deployment.html?utm_source=github&utm_campaign=focalboard). After logging into Mattermost, select the menu in the top left corner and select **Boards**. ### Personal Desktop (Windows, Mac or Linux Desktop) @@ -48,7 +51,7 @@ Boards API docs can be found over at https://htmlpreview.github.io/?https://gith ## Contribute to Focalboard -Contribute code, bug reports, and ideas to the future of the Focalboard project. We welcome your input! Please see [CONTRIBUTING](CONTRIBUTING.md) for details on how to get involved. +For anyone interested in being an official maintainer of the Focalboard repository, please reach out to us on our [Focalboard Community Channel](https://community.mattermost.com/core/channels/focalboard). If there are no maintainers, and you’re still interested in adding your own improvements to the Focalboard Personal Editions, we encourage you to fork and maintain the repository. ### Getting started @@ -134,8 +137,6 @@ Help translate Focalboard! The app is already translated into several languages. ### Staying informed -Are you interested in influencing the future of the Focalboard open source project? Here's how you can get involved: - * **Changes**: See the [CHANGELOG](CHANGELOG.md) for the latest updates * **GitHub Discussions**: Join the [Developer Discussion](https://github.com/mattermost/focalboard/discussions) board * **Bug Reports**: [File a bug report](https://github.com/mattermost/focalboard/issues/new?assignees=&labels=bug&template=bug_report.md&title=) From 2b9eec1bec0437f7389e506a92735ff7f160506c Mon Sep 17 00:00:00 2001 From: Doug Lauder Date: Mon, 3 Apr 2023 17:43:58 -0400 Subject: [PATCH 045/102] Avoid panic in file request handler on error (#4693) Co-authored-by: Mattermost Build --- server/api/files.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/server/api/files.go b/server/api/files.go index c2a6eaa71..2868e5507 100644 --- a/server/api/files.go +++ b/server/api/files.go @@ -19,6 +19,7 @@ import ( "github.com/mattermost/focalboard/server/model" "github.com/mattermost/focalboard/server/services/audit" + mmModel "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/shared/mlog" @@ -167,7 +168,14 @@ func (a *API) handleServeFile(w http.ResponseWriter, r *http.Request) { _ = a.app.MoveFile(board.ChannelID, board.TeamID, boardID, filename) } + if err != nil { + // if err is still not nil then it is an error other than `not found` so we must + // return the error to the requestor. fileReader and Fileinfo are nil in this case. + a.errorResponse(w, r, err) + } + defer fileReader.Close() + mimeType := "" var fileSize int64 if fileInfo != nil { From dc0e664df90e5773fd05a7a33e6a7ca82a85cb91 Mon Sep 17 00:00:00 2001 From: Caleb Roseland Date: Tue, 4 Apr 2023 14:29:49 -0500 Subject: [PATCH 046/102] Backport: MM-51842: fix value-change detection in number properties (#4694) --- .../number/__snapshots__/number.test.tsx.snap | 13 ++++ webapp/src/properties/number/number.test.tsx | 72 +++++++++++++++++++ webapp/src/properties/number/number.tsx | 2 +- 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 webapp/src/properties/number/__snapshots__/number.test.tsx.snap create mode 100644 webapp/src/properties/number/number.test.tsx diff --git a/webapp/src/properties/number/__snapshots__/number.test.tsx.snap b/webapp/src/properties/number/__snapshots__/number.test.tsx.snap new file mode 100644 index 000000000..8e914cd2c --- /dev/null +++ b/webapp/src/properties/number/__snapshots__/number.test.tsx.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`properties/number should match snapshot for number with empty value 1`] = ` +
+ +
+`; diff --git a/webapp/src/properties/number/number.test.tsx b/webapp/src/properties/number/number.test.tsx new file mode 100644 index 000000000..6bb9194b1 --- /dev/null +++ b/webapp/src/properties/number/number.test.tsx @@ -0,0 +1,72 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React, {ComponentProps} from 'react' +import {render, screen} from '@testing-library/react' +import {mocked} from 'jest-mock' + +import userEvent from '@testing-library/user-event' + +import {wrapIntl} from '../../testUtils' +import {TestBlockFactory} from '../../test/testBlockFactory' +import mutator from '../../mutator' + +import {Board, IPropertyTemplate} from '../..//blocks/board' +import {Card} from '../../blocks/card' + +import NumberProperty from './property' +import NumberEditor from './number' + +jest.mock('../../components/flashMessages') +jest.mock('../../mutator') + +const mockedMutator = mocked(mutator) + +describe('properties/number', () => { + let board: Board + let card: Card + let propertyTemplate: IPropertyTemplate + let baseProps: ComponentProps + + beforeEach(() => { + board = TestBlockFactory.createBoard() + card = TestBlockFactory.createCard() + propertyTemplate = board.cardProperties[0] + + baseProps = { + property: new NumberProperty(), + card, + board, + propertyTemplate, + propertyValue: '', + readOnly: false, + showEmptyPlaceholder: false, + } + }) + + it('should match snapshot for number with empty value', () => { + const {container} = render( + wrapIntl(( + + )), + ) + expect(container).toMatchSnapshot() + }) + + it('should fire change event when valid number value is entered', async () => { + render( + wrapIntl( + , + ), + ) + const value = '42' + const input = screen.getByRole('textbox') + userEvent.type(input, `${value}{Enter}`) + + expect(mockedMutator.changePropertyValue).toHaveBeenCalledWith(board.id, card, propertyTemplate.id, `${value}`) + }) +}) diff --git a/webapp/src/properties/number/number.tsx b/webapp/src/properties/number/number.tsx index b22b43105..5f607f9eb 100644 --- a/webapp/src/properties/number/number.tsx +++ b/webapp/src/properties/number/number.tsx @@ -10,7 +10,7 @@ const Number = (props: PropertyProps): JSX.Element => { return ( !isNaN(parseInt(props.propertyValue as string, 10))} + validator={() => props.propertyValue === '' || !isNaN(parseInt(props.propertyValue as string, 10))} /> ) } From 615b6ceee7d490d2988d93d3b7facd4f7f48aa48 Mon Sep 17 00:00:00 2001 From: Winson Wu <93531870+wuwinson@users.noreply.github.com> Date: Mon, 24 Apr 2023 17:01:21 -0400 Subject: [PATCH 047/102] Update README.md Updated announcement to make it more obvious. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b94073679..fa837cb4a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# Announcement +# :warning: Announcement: PLEASE READ :warning: Focalboard Personal Server and Personal Desktop editions will transition to being fully community supported as of **April 30th, 2023**. This Focalboard repository will become the Personal Edition repository, and will remain open indefinitely. However, we won’t be adding any new enhancements, and will only address Sev-1 level bugs until April 30th, 2023. -The Boards plugin version will be integrated into Mattermost as a core in-product feature, and will no longer be supported as a plugin as of release v7.11 (May 2023). The plugin code will be merged into the [Mattermost-server repository](https://github.com/mattermost/mattermost-server) where future enhancements will be added to moving forward. +The Boards plugin version will be integrated into Mattermost as a core in-product feature, and will no longer be supported as a plugin as of release v7.11 (May 2023). The plugin code will be merged into the [Mattermost-server repository](https://github.com/mattermost/mattermost-server) where future enhancements will be added to moving forward. New pull requests and issues should be filed against https://github.com/mattermost/mattermost-server. Please see [this dicussion](https://github.com/mattermost/focalboard/discussions/4645) for more details. From acc9750d972806561e8e6acb996566c32be51672 Mon Sep 17 00:00:00 2001 From: Miguel de la Cruz Date: Wed, 26 Apr 2023 22:01:47 +0200 Subject: [PATCH 048/102] Add table_schema filter when checking for migrations table shape (#4717) --- server/services/store/sqlstore/schema_table_migration.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/server/services/store/sqlstore/schema_table_migration.go b/server/services/store/sqlstore/schema_table_migration.go index 2ab075658..1347fd986 100644 --- a/server/services/store/sqlstore/schema_table_migration.go +++ b/server/services/store/sqlstore/schema_table_migration.go @@ -123,6 +123,13 @@ func (s *SQLStore) isSchemaMigrationNeeded() (bool, error) { "TABLE_NAME": s.tablePrefix + "schema_migrations", }) + switch s.dbType { + case model.MysqlDBType: + query = query.Where(sq.Eq{"TABLE_SCHEMA": s.schemaName}) + case model.PostgresDBType: + query = query.Where("table_schema = current_schema()") + } + rows, err := query.Query() if err != nil { s.logger.Error("failed to fetch columns in schema_migrations table", mlog.Err(err)) From 799b8ead1cc1f8d7b2949fe08403f77032bab244 Mon Sep 17 00:00:00 2001 From: Miguel de la Cruz Date: Wed, 26 Apr 2023 22:41:27 +0200 Subject: [PATCH 049/102] Adds a retry count to the websocket re-open flow (#4722) * Adds a retry count to the websocket re-open flow * Fix linter --- webapp/src/wsclient.ts | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/webapp/src/wsclient.ts b/webapp/src/wsclient.ts index e88ab2043..893e68d55 100644 --- a/webapp/src/wsclient.ts +++ b/webapp/src/wsclient.ts @@ -127,6 +127,8 @@ class WSClient { onUnfollowBlock: FollowChangeHandler = () => {} private notificationDelay = 100 private reopenDelay = 3000 + private reopenRetryCount = 0 + private reopenMaxRetries = 10 private updatedData: UpdatedData = {Blocks: [], Categories: [], BoardCategories: [], Boards: [], BoardMembers: [], CategoryOrder: []} private updateTimeout?: NodeJS.Timeout private errorPollId?: NodeJS.Timeout @@ -400,6 +402,7 @@ class WSClient { ws.onopen = () => { Utils.log('WSClient webSocket opened.') this.state = 'open' + this.reopenRetryCount = 0 // if has a token defined when connecting, authenticate if (this.token) { @@ -426,19 +429,25 @@ class WSClient { Utils.log(`WSClient websocket onclose, code: ${e.code}, reason: ${e.reason}`) if (ws === this.ws) { // Unexpected close, re-open - Utils.logError('Unexpected close, re-opening websocket') + Utils.logError('Unexpected WSClient close') for (const handler of this.onStateChange) { handler(this, 'close') } this.state = 'close' - setTimeout(() => { - // ToDo: assert that this actually runs the onopen - // contents (auth + this.subscribe()) - this.open() - for (const handler of this.onReconnect) { - handler(this) - } - }, this.reopenDelay) + + if (this.reopenRetryCount < this.reopenMaxRetries) { + setTimeout(() => { + this.reopenRetryCount++ + Utils.log(`Reopening websocket connection, count: ${this.reopenRetryCount}`) + + this.open() + for (const handler of this.onReconnect) { + handler(this) + } + }, this.reopenDelay) + } else { + Utils.logError('Reached max websocket re-opening attempts') + } } } From c9acca6acbdfc4b6fa966962888178d9265df28c Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Fri, 28 Apr 2023 10:56:32 -0600 Subject: [PATCH 050/102] check permissions for personal server (#4726) * check permissions for personal server * remove import --- webapp/src/hooks/permissions.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/webapp/src/hooks/permissions.tsx b/webapp/src/hooks/permissions.tsx index a050d45e5..b8d1d0804 100644 --- a/webapp/src/hooks/permissions.tsx +++ b/webapp/src/hooks/permissions.tsx @@ -4,7 +4,6 @@ import {useAppSelector} from '../store/hooks' import {getMyBoardMembership, getCurrentBoardId, getBoard} from '../store/boards' import {getCurrentTeam} from '../store/teams' -import {Utils} from '../utils' import {Permission} from '../constants' import {MemberRole} from '../blocks/board' @@ -24,10 +23,6 @@ export const useHasPermissions = (teamId: string, boardId: string, permissions: return false } - if (!Utils.isFocalboardPlugin()) { - return true - } - const adminPermissions = [Permission.ManageBoardType, Permission.DeleteBoard, Permission.ShareBoard, Permission.ManageBoardRoles, Permission.DeleteOthersComments] const editorPermissions = [Permission.ManageBoardCards, Permission.ManageBoardProperties] const commenterPermissions = [Permission.CommentBoardCards] From 252f2138ca5532343b50898aa3a761bddc70f940 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Fri, 28 Apr 2023 11:03:27 -0600 Subject: [PATCH 051/102] fix so dropping on card has latest cards objects (#4725) Co-authored-by: Mattermost Build --- webapp/src/components/kanban/kanban.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/src/components/kanban/kanban.tsx b/webapp/src/components/kanban/kanban.tsx index 190895fcf..d341f39bc 100644 --- a/webapp/src/components/kanban/kanban.tsx +++ b/webapp/src/components/kanban/kanban.tsx @@ -203,7 +203,7 @@ const Kanban = (props: Props) => { await Promise.all(awaits) await mutator.changeViewCardOrder(props.board.id, activeView.id, activeView.fields.cardOrder, cardOrder, description) }) - }, [cards.map((o) => o.id).join(','), activeView.id, activeView.fields.cardOrder, groupByProperty, props.selectedCardIds]) + }, [cards, activeView.id, activeView.fields.cardOrder, groupByProperty, props.selectedCardIds]) const [showCalculationsMenu, setShowCalculationsMenu] = useState>(new Map()) const toggleOptions = (templateId: string, show: boolean) => { From 0af70a0a4f2ae1c11633d4431f4db70db1640337 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Mon, 8 May 2023 10:40:14 -0600 Subject: [PATCH 052/102] fix issue with card id being valid block but not a card (#4729) --- .../__snapshots__/boardsUnfurl.test.tsx.snap | 6 + .../boardsUnfurl/boardsUnfurl.test.tsx | 115 ++++++++++++++++++ .../components/boardsUnfurl/boardsUnfurl.tsx | 4 +- 3 files changed, 123 insertions(+), 2 deletions(-) diff --git a/mattermost-plugin/webapp/src/components/boardsUnfurl/__snapshots__/boardsUnfurl.test.tsx.snap b/mattermost-plugin/webapp/src/components/boardsUnfurl/__snapshots__/boardsUnfurl.test.tsx.snap index bbf4ddc41..cfe233747 100644 --- a/mattermost-plugin/webapp/src/components/boardsUnfurl/__snapshots__/boardsUnfurl.test.tsx.snap +++ b/mattermost-plugin/webapp/src/components/boardsUnfurl/__snapshots__/boardsUnfurl.test.tsx.snap @@ -96,3 +96,9 @@ exports[`components/boardsUnfurl/BoardsUnfurl renders when limited 1`] = `
`; + +exports[`components/boardsUnfurl/BoardsUnfurl test invalid card, invalid block 1`] = `
`; + +exports[`components/boardsUnfurl/BoardsUnfurl test invalid card, valid block 1`] = `
`; + +exports[`components/boardsUnfurl/BoardsUnfurl test no card 1`] = `
`; diff --git a/mattermost-plugin/webapp/src/components/boardsUnfurl/boardsUnfurl.test.tsx b/mattermost-plugin/webapp/src/components/boardsUnfurl/boardsUnfurl.test.tsx index 30d4f360b..79dd8f555 100644 --- a/mattermost-plugin/webapp/src/components/boardsUnfurl/boardsUnfurl.test.tsx +++ b/mattermost-plugin/webapp/src/components/boardsUnfurl/boardsUnfurl.test.tsx @@ -10,6 +10,8 @@ import {Provider as ReduxProvider} from 'react-redux' import {mocked} from 'jest-mock' +import {createBoardView} from '../../../../../webapp/src/blocks/boardView' + import {Utils} from '../../../../../webapp/src/utils' import {createCard} from '../../../../../webapp/src/blocks/card' import {createBoard} from '../../../../../webapp/src/blocks/board' @@ -116,5 +118,118 @@ describe('components/boardsUnfurl/BoardsUnfurl', () => { expect(container).toMatchSnapshot() }) + + it('test no card', async () => { + const mockStore = configureStore([]) + const store = mockStore({ + language: { + value: 'en', + }, + teams: { + allTeams: [team], + current: team, + }, + }) + + const board = {...createBoard(), title: 'test board'} + // mockedOctoClient.getBoard.mockResolvedValueOnce(board) + + const component = ( + + {wrapIntl( + , + )} + + ) + + let container: Element | DocumentFragment | null = null + + await act(async () => { + const result = render(component) + container = result.container + }) + expect(container).toMatchSnapshot() + }) + + it('test invalid card, valid block', async () => { + const mockStore = configureStore([]) + const store = mockStore({ + language: { + value: 'en', + }, + teams: { + allTeams: [team], + current: team, + }, + }) + + const cards = [{...createBoardView(), title: 'test view', updateAt: 12345}] + const board = {...createBoard(), title: 'test board'} + + mockedOctoClient.getBlocksWithBlockID.mockResolvedValueOnce(cards) + mockedOctoClient.getBoard.mockResolvedValueOnce(board) + + const component = ( + + {wrapIntl( + , + )} + + ) + + let container: Element | DocumentFragment | null = null + + await act(async () => { + const result = render(component) + container = result.container + }) + expect(mockedOctoClient.getBoard).toBeCalledWith(board.id) + expect(mockedOctoClient.getBlocksWithBlockID).toBeCalledWith(cards[0].id, board.id, 'abc') + + expect(container).toMatchSnapshot() + }) + + it('test invalid card, invalid block', async () => { + const mockStore = configureStore([]) + const store = mockStore({ + language: { + value: 'en', + }, + teams: { + allTeams: [team], + current: team, + }, + }) + + const board = {...createBoard(), title: 'test board'} + + mockedOctoClient.getBlocksWithBlockID.mockResolvedValueOnce([]) + mockedOctoClient.getBoard.mockResolvedValueOnce(board) + + const component = ( + + {wrapIntl( + , + )} + + ) + + let container: Element | DocumentFragment | null = null + + await act(async () => { + const result = render(component) + container = result.container + }) + expect(mockedOctoClient.getBoard).toBeCalledWith(board.id) + expect(mockedOctoClient.getBlocksWithBlockID).toBeCalledWith('invalidCard', board.id, 'abc') + + expect(container).toMatchSnapshot() + }) }) diff --git a/mattermost-plugin/webapp/src/components/boardsUnfurl/boardsUnfurl.tsx b/mattermost-plugin/webapp/src/components/boardsUnfurl/boardsUnfurl.tsx index f1e7a5378..ad8883c96 100644 --- a/mattermost-plugin/webapp/src/components/boardsUnfurl/boardsUnfurl.tsx +++ b/mattermost-plugin/webapp/src/components/boardsUnfurl/boardsUnfurl.tsx @@ -84,7 +84,7 @@ export const BoardsUnfurl = (props: Props): JSX.Element => { ], ) const [firstCard] = cards as Card[] - if (!firstCard || !fetchedBoard) { + if (!firstCard || !fetchedBoard || firstCard.type !== 'card') { setLoading(false) return null } @@ -116,7 +116,7 @@ export const BoardsUnfurl = (props: Props): JSX.Element => { useWebsockets(currentTeamId, (wsClient: WSClient) => { const onChangeHandler = (_: WSClient, blocks: Block[]): void => { const cardBlock: Block|undefined = blocks.find(b => b.id === cardID) - if (cardBlock && !cardBlock.deleteAt) { + if (cardBlock && !cardBlock.deleteAt && cardBlock.type === 'card') { setCard(cardBlock as Card) } From d10e4070ba2bea4326b06b815bf4a6bdf01257d2 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Thu, 11 May 2023 08:06:06 -0600 Subject: [PATCH 053/102] Fix public boards setting not applying properly (#4739) --- server/auth/auth.go | 4 +++ server/integrationtests/permissions_test.go | 29 +++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/server/auth/auth.go b/server/auth/auth.go index 5572a3d19..1a1e29cb6 100644 --- a/server/auth/auth.go +++ b/server/auth/auth.go @@ -54,6 +54,10 @@ func (a *Auth) IsValidReadToken(boardID string, readToken string) (bool, error) return false, err } + if !a.config.EnablePublicSharedBoards { + return false, errors.New("public shared boards disabled") + } + if sharing != nil && (sharing.ID == boardID && sharing.Enabled && sharing.Token == readToken) { return true, nil } diff --git a/server/integrationtests/permissions_test.go b/server/integrationtests/permissions_test.go index 6cea0e1d8..323ed7a3a 100644 --- a/server/integrationtests/permissions_test.go +++ b/server/integrationtests/permissions_test.go @@ -581,6 +581,35 @@ func TestPermissionsGetBoard(t *testing.T) { }) } +func TestPermissionsGetBoardPublic(t *testing.T) { + ttCases := []TestCase{ + {"/boards/{PRIVATE_BOARD_ID}?read_token=invalid", methodGet, "", userAnon, http.StatusUnauthorized, 0}, + {"/boards/{PRIVATE_BOARD_ID}?read_token=valid", methodGet, "", userAnon, http.StatusUnauthorized, 1}, + {"/boards/{PRIVATE_BOARD_ID}?read_token=invalid", methodGet, "", userNoTeamMember, http.StatusForbidden, 0}, + {"/boards/{PRIVATE_BOARD_ID}?read_token=valid", methodGet, "", userTeamMember, http.StatusForbidden, 1}, + } + t.Run("plugin", func(t *testing.T) { + th := SetupTestHelperPluginMode(t) + defer th.TearDown() + cfg := th.Server.Config() + cfg.EnablePublicSharedBoards = false + th.Server.UpdateAppConfig() + clients := setupClients(th) + testData := setupData(t, th) + runTestCases(t, ttCases, testData, clients) + }) + t.Run("local", func(t *testing.T) { + th := SetupTestHelperLocalMode(t) + defer th.TearDown() + cfg := th.Server.Config() + cfg.EnablePublicSharedBoards = false + th.Server.UpdateAppConfig() + clients := setupLocalClients(th) + testData := setupData(t, th) + runTestCases(t, ttCases, testData, clients) + }) +} + func TestPermissionsPatchBoard(t *testing.T) { ttCases := []TestCase{ {"/boards/{PRIVATE_BOARD_ID}", methodPatch, "{\"title\": \"test\"}", userAnon, http.StatusUnauthorized, 0}, From b7d94a8fe26ac784ed831caf6a54b719b9907450 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Mon, 22 May 2023 05:11:06 -0600 Subject: [PATCH 054/102] update to version v7.11.0 (#4742) --- mattermost-plugin/plugin.json | 2 +- mattermost-plugin/server/manifest.go | 2 +- server/model/version.go | 1 + webapp/package-lock.json | 4 ++-- webapp/package.json | 2 +- .../__snapshots__/globalHeader.test.tsx.snap | 2 +- .../__snapshots__/sidebar.test.tsx.snap | 20 +++++++++---------- webapp/src/constants.ts | 4 ++-- 8 files changed, 19 insertions(+), 18 deletions(-) diff --git a/mattermost-plugin/plugin.json b/mattermost-plugin/plugin.json index a02f513bc..968d898c6 100644 --- a/mattermost-plugin/plugin.json +++ b/mattermost-plugin/plugin.json @@ -6,7 +6,7 @@ "support_url": "https://github.com/mattermost/focalboard/issues", "release_notes_url": "https://github.com/mattermost/focalboard/releases", "icon_path": "assets/starter-template-icon.svg", - "version": "7.10.0", + "version": "7.11.0", "min_server_version": "7.2.0", "server": { "executables": { diff --git a/mattermost-plugin/server/manifest.go b/mattermost-plugin/server/manifest.go index 66bea8178..615e216f5 100644 --- a/mattermost-plugin/server/manifest.go +++ b/mattermost-plugin/server/manifest.go @@ -20,7 +20,7 @@ const manifestStr = ` "support_url": "https://github.com/mattermost/focalboard/issues", "release_notes_url": "https://github.com/mattermost/focalboard/releases", "icon_path": "assets/starter-template-icon.svg", - "version": "7.10.0", + "version": "7.11.0", "min_server_version": "7.2.0", "server": { "executables": { diff --git a/server/model/version.go b/server/model/version.go index 52fe08e79..932daf832 100644 --- a/server/model/version.go +++ b/server/model/version.go @@ -8,6 +8,7 @@ import ( // It should be maintained in chronological order with most current // release at the front of the list. var versions = []string{ + "7.11.0", "7.10.0", "7.9.0", "7.8.0", diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 9de98ccbd..e122f1ab5 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -1,12 +1,12 @@ { "name": "focalboard", - "version": "7.10.0", + "version": "7.11.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "focalboard", - "version": "7.10.0", + "version": "7.11.0", "dependencies": { "@draft-js-plugins/editor": "^4.1.2", "@draft-js-plugins/emoji": "^4.6.0", diff --git a/webapp/package.json b/webapp/package.json index 935c76e31..f3729cd98 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -1,6 +1,6 @@ { "name": "focalboard", - "version": "7.10.0", + "version": "7.11.0", "private": true, "description": "", "scripts": { diff --git a/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap b/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap index ffd6d4819..69dbc4f9d 100644 --- a/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap +++ b/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap @@ -10,7 +10,7 @@ exports[`components/sidebar/GlobalHeader header menu should match snapshot 1`] = /> diff --git a/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap b/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap index 4533b2b83..0320ed43c 100644 --- a/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap +++ b/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap @@ -51,9 +51,9 @@ exports[`components/sidebarSidebar dont show hidden boards 1`] = ` >
- v7.10.0 + v7.11.0
@@ -252,9 +252,9 @@ exports[`components/sidebarSidebar should assign default category if current boa >
- v7.10.0 + v7.11.0
@@ -508,9 +508,9 @@ exports[`components/sidebarSidebar shouldnt do any category assignment is board >
- v7.10.0 + v7.11.0
@@ -919,9 +919,9 @@ exports[`components/sidebarSidebar sidebar hidden 1`] = ` >
- v7.10.0 + v7.11.0
@@ -1213,9 +1213,9 @@ exports[`components/sidebarSidebar some categories hidden 1`] = ` >
- v7.10.0 + v7.11.0
diff --git a/webapp/src/constants.ts b/webapp/src/constants.ts index 9331eebe4..f750d5e81 100644 --- a/webapp/src/constants.ts +++ b/webapp/src/constants.ts @@ -37,8 +37,8 @@ class Constants { static readonly titleColumnId = '__title' static readonly badgesColumnId = '__badges' - static readonly versionString = '7.10.0' - static readonly versionDisplayString = 'Apr 2023' + static readonly versionString = '7.11.0' + static readonly versionDisplayString = 'May 2023' static readonly archiveHelpPage = 'https://docs.mattermost.com/boards/migrate-to-boards.html' static readonly imports = [ From 888c169910687a171e0f4e86f7c7ed4b24acb310 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Mon, 22 May 2023 10:31:24 -0600 Subject: [PATCH 055/102] Backport fixes for import/export attachments and fixes (#4741) * Backport fixes for import/export attachments and fixes * fix bad merge * lint fixes * Update server/app/boards.go Co-authored-by: Miguel de la Cruz --------- Co-authored-by: Miguel de la Cruz --- server/api/blocks.go | 2 +- server/api/files.go | 2 +- server/app/blocks.go | 96 +------ server/app/boards.go | 47 +--- server/app/export.go | 24 +- server/app/files.go | 224 +++++++++++---- server/app/files_test.go | 260 +++++++++++++++--- server/app/import.go | 110 +++++--- server/app/import_test.go | 71 ++++- server/app/templates_test.go | 1 + server/integrationtests/permissions_test.go | 4 +- server/model/file.go | 25 ++ webapp/src/blocks/attachmentBlock.tsx | 4 +- webapp/src/components/cardDialog.tsx | 8 +- .../content/attachmentElement.test.tsx | 2 +- .../components/content/attachmentElement.tsx | 4 +- 16 files changed, 591 insertions(+), 293 deletions(-) create mode 100644 server/model/file.go diff --git a/server/api/blocks.go b/server/api/blocks.go index 89b7127a4..1d9f83e45 100644 --- a/server/api/blocks.go +++ b/server/api/blocks.go @@ -303,7 +303,7 @@ func (a *API) handlePostBlocks(w http.ResponseWriter, r *http.Request) { // this query param exists when creating template from board, or board from template sourceBoardID := r.URL.Query().Get("sourceBoardID") if sourceBoardID != "" { - if updateFileIDsErr := a.app.CopyCardFiles(sourceBoardID, blocks); updateFileIDsErr != nil { + if updateFileIDsErr := a.app.CopyAndUpdateCardFiles(sourceBoardID, userID, blocks, false); updateFileIDsErr != nil { a.errorResponse(w, r, updateFileIDsErr) return } diff --git a/server/api/files.go b/server/api/files.go index 2868e5507..609a9e53b 100644 --- a/server/api/files.go +++ b/server/api/files.go @@ -393,7 +393,7 @@ func (a *API) handleUploadFile(w http.ResponseWriter, r *http.Request) { auditRec.AddMeta("teamID", board.TeamID) auditRec.AddMeta("filename", handle.Filename) - fileID, err := a.app.SaveFile(file, board.TeamID, boardID, handle.Filename) + fileID, err := a.app.SaveFile(file, board.TeamID, boardID, handle.Filename, board.IsTemplate) if err != nil { a.errorResponse(w, r, err) return diff --git a/server/app/blocks.go b/server/app/blocks.go index 3ed9d39d4..41fd233a8 100644 --- a/server/app/blocks.go +++ b/server/app/blocks.go @@ -4,11 +4,9 @@ import ( "errors" "fmt" "path/filepath" - "strings" "github.com/mattermost/focalboard/server/model" "github.com/mattermost/focalboard/server/services/notify" - "github.com/mattermost/focalboard/server/utils" "github.com/mattermost/mattermost-server/v6/shared/mlog" ) @@ -45,6 +43,11 @@ func (a *App) DuplicateBlock(boardID string, blockID string, userID string, asTe return nil, err } + err = a.CopyAndUpdateCardFiles(boardID, userID, blocks, asTemplate) + if err != nil { + return nil, err + } + a.blockChangeNotifier.Enqueue(func() error { for _, block := range blocks { a.wsAdapter.BroadcastBlockChange(board.TeamID, block) @@ -292,95 +295,6 @@ func (a *App) InsertBlocksAndNotify(blocks []*model.Block, modifiedByID string, return blocks, nil } -func (a *App) CopyCardFiles(sourceBoardID string, copiedBlocks []*model.Block) error { - // Images attached in cards have a path comprising the card's board ID. - // When we create a template from this board, we need to copy the files - // with the new board ID in path. - // Not doing so causing images in templates (and boards created from this - // template) to fail to load. - - // look up ID of source sourceBoard, which may be different than the blocks. - sourceBoard, err := a.GetBoard(sourceBoardID) - if err != nil || sourceBoard == nil { - return fmt.Errorf("cannot fetch source board %s for CopyCardFiles: %w", sourceBoardID, err) - } - - var destTeamID string - var destBoardID string - - for i := range copiedBlocks { - block := copiedBlocks[i] - fileName := "" - isOk := false - - switch block.Type { - case model.TypeImage: - fileName, isOk = block.Fields["fileId"].(string) - if !isOk || fileName == "" { - continue - } - case model.TypeAttachment: - fileName, isOk = block.Fields["attachmentId"].(string) - if !isOk || fileName == "" { - continue - } - default: - continue - } - - // create unique filename in case we are copying cards within the same board. - ext := filepath.Ext(fileName) - destFilename := utils.NewID(utils.IDTypeNone) + ext - - if destBoardID == "" || block.BoardID != destBoardID { - destBoardID = block.BoardID - destBoard, err := a.GetBoard(destBoardID) - if err != nil { - return fmt.Errorf("cannot fetch destination board %s for CopyCardFiles: %w", sourceBoardID, err) - } - destTeamID = destBoard.TeamID - } - - sourceFilePath := filepath.Join(sourceBoard.TeamID, sourceBoard.ID, fileName) - destinationFilePath := filepath.Join(destTeamID, block.BoardID, destFilename) - - a.logger.Debug( - "Copying card file", - mlog.String("sourceFilePath", sourceFilePath), - mlog.String("destinationFilePath", destinationFilePath), - ) - - if err := a.filesBackend.CopyFile(sourceFilePath, destinationFilePath); err != nil { - a.logger.Error( - "CopyCardFiles failed to copy file", - mlog.String("sourceFilePath", sourceFilePath), - mlog.String("destinationFilePath", destinationFilePath), - mlog.Err(err), - ) - } - if block.Type == model.TypeAttachment { - block.Fields["attachmentId"] = destFilename - parts := strings.Split(fileName, ".") - fileInfoID := parts[0][1:] - fileInfo, err := a.store.GetFileInfo(fileInfoID) - if err != nil { - return fmt.Errorf("CopyCardFiles: cannot retrieve original fileinfo: %w", err) - } - newParts := strings.Split(destFilename, ".") - newFileID := newParts[0][1:] - fileInfo.Id = newFileID - err = a.store.SaveFileInfo(fileInfo) - if err != nil { - return fmt.Errorf("CopyCardFiles: cannot create fileinfo: %w", err) - } - } else { - block.Fields["fileId"] = destFilename - } - } - - return nil -} - func (a *App) GetBlockByID(blockID string) (*model.Block, error) { return a.store.GetBlock(blockID) } diff --git a/server/app/boards.go b/server/app/boards.go index d31bd573c..416e69891 100644 --- a/server/app/boards.go +++ b/server/app/boards.go @@ -185,8 +185,13 @@ func (a *App) DuplicateBoard(boardID, userID, toTeam string, asTemplate bool) (* } // copy any file attachments from the duplicated blocks. - if err = a.CopyCardFiles(boardID, bab.Blocks); err != nil { - a.logger.Error("Could not copy files while duplicating board", mlog.String("BoardID", boardID), mlog.Err(err)) + err = a.CopyAndUpdateCardFiles(boardID, userID, bab.Blocks, asTemplate) + if err != nil { + dbab := model.NewDeleteBoardsAndBlocksFromBabs(bab) + if dErr := a.store.DeleteBoardsAndBlocks(dbab, userID); dErr != nil { + a.logger.Error("Cannot delete board after duplication error when updating block's file info", mlog.String("boardID", bab.Boards[0].ID), mlog.Err(dErr)) + } + return nil, nil, fmt.Errorf("could not patch file IDs while duplicating board %s: %w", boardID, err) } if !asTemplate { @@ -197,44 +202,6 @@ func (a *App) DuplicateBoard(boardID, userID, toTeam string, asTemplate bool) (* } } - // bab.Blocks now has updated file ids for any blocks containing files. We need to store them. - blockIDs := make([]string, 0) - blockPatches := make([]model.BlockPatch, 0) - - for _, block := range bab.Blocks { - fieldName := "" - if block.Type == model.TypeImage { - fieldName = "fileId" - } else if block.Type == model.TypeAttachment { - fieldName = "attachmentId" - } - if fieldName != "" { - if fieldID, ok := block.Fields[fieldName]; ok { - blockIDs = append(blockIDs, block.ID) - blockPatches = append(blockPatches, model.BlockPatch{ - UpdatedFields: map[string]interface{}{ - fieldName: fieldID, - }, - }) - } - } - } - a.logger.Debug("Duplicate boards patching file IDs", mlog.Int("count", len(blockIDs))) - - if len(blockIDs) != 0 { - patches := &model.BlockPatchBatch{ - BlockIDs: blockIDs, - BlockPatches: blockPatches, - } - if err = a.store.PatchBlocks(patches, userID); err != nil { - dbab := model.NewDeleteBoardsAndBlocksFromBabs(bab) - if err = a.store.DeleteBoardsAndBlocks(dbab, userID); err != nil { - a.logger.Error("Cannot delete board after duplication error when updating block's file info", mlog.String("boardID", bab.Boards[0].ID), mlog.Err(err)) - } - return nil, nil, fmt.Errorf("could not patch file IDs while duplicating board %s: %w", boardID, err) - } - } - a.blockChangeNotifier.Enqueue(func() error { teamID := "" for _, board := range bab.Boards { diff --git a/server/app/export.go b/server/app/export.go index 81cf07e71..bd110ac92 100644 --- a/server/app/export.go +++ b/server/app/export.go @@ -91,10 +91,10 @@ func (a *App) writeArchiveBoard(zw *zip.Writer, board model.Board, opt model.Exp if err = a.writeArchiveBlockLine(w, block); err != nil { return err } - if block.Type == model.TypeImage { - filename, err2 := extractImageFilename(block) + if block.Type == model.TypeImage || block.Type == model.TypeAttachment { + filename, err2 := extractFilename(block) if err2 != nil { - return err + return err2 } files = append(files, filename) } @@ -204,7 +204,10 @@ func (a *App) writeArchiveFile(zw *zip.Writer, filename string, boardID string, return err } - src, err := a.GetFileReader(opt.TeamID, boardID, filename) + _, fileReader, err := a.GetFile(opt.TeamID, boardID, filename) + if err != nil && !model.IsErrNotFound(err) { + return err + } if err != nil { // just log this; image file is missing but we'll still export an equivalent board a.logger.Error("image file missing for export", @@ -214,9 +217,9 @@ func (a *App) writeArchiveFile(zw *zip.Writer, filename string, boardID string, ) return nil } - defer src.Close() + defer fileReader.Close() - _, err = io.Copy(dest, src) + _, err = io.Copy(dest, fileReader) return err } @@ -235,10 +238,13 @@ func (a *App) getBoardsForArchive(boardIDs []string) ([]model.Board, error) { return boards, nil } -func extractImageFilename(imageBlock *model.Block) (string, error) { - f, ok := imageBlock.Fields["fileId"] +func extractFilename(block *model.Block) (string, error) { + f, ok := block.Fields["fileId"] if !ok { - return "", model.ErrInvalidImageBlock + f, ok = block.Fields["attachmentId"] + if !ok { + return "", model.ErrInvalidImageBlock + } } filename, ok := f.(string) diff --git a/server/app/files.go b/server/app/files.go index 1474a291a..b45726756 100644 --- a/server/app/files.go +++ b/server/app/files.go @@ -8,19 +8,17 @@ import ( "strings" "github.com/mattermost/focalboard/server/model" - mmModel "github.com/mattermost/mattermost-server/v6/model" + mm_model "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/focalboard/server/utils" "github.com/mattermost/mattermost-server/v6/shared/filestore" "github.com/mattermost/mattermost-server/v6/shared/mlog" ) -const emptyString = "empty" - var errEmptyFilename = errors.New("IsFileArchived: empty filename not allowed") var ErrFileNotFound = errors.New("file not found") -func (a *App) SaveFile(reader io.Reader, teamID, rootID, filename string) (string, error) { +func (a *App) SaveFile(reader io.Reader, teamID, boardID, filename string, asTemplate bool) (string, error) { // NOTE: File extension includes the dot fileExtension := strings.ToLower(filepath.Ext(filename)) if fileExtension == ".jpeg" { @@ -28,48 +26,31 @@ func (a *App) SaveFile(reader io.Reader, teamID, rootID, filename string) (strin } createdFilename := utils.NewID(utils.IDTypeNone) - fullFilename := fmt.Sprintf(`%s%s`, createdFilename, fileExtension) - filePath := filepath.Join(utils.GetBaseFilePath(), fullFilename) + newFileName := fmt.Sprintf(`%s%s`, createdFilename, fileExtension) + if asTemplate { + newFileName = filename + } + filePath := getDestinationFilePath(asTemplate, teamID, boardID, newFileName) fileSize, appErr := a.filesBackend.WriteFile(reader, filePath) if appErr != nil { return "", fmt.Errorf("unable to store the file in the files storage: %w", appErr) } - now := utils.GetMillis() - - fileInfo := &mmModel.FileInfo{ - Id: createdFilename[1:], - CreatorId: "boards", - PostId: emptyString, - ChannelId: emptyString, - CreateAt: now, - UpdateAt: now, - DeleteAt: 0, - Path: filePath, - ThumbnailPath: emptyString, - PreviewPath: emptyString, - Name: filename, - Extension: fileExtension, - Size: fileSize, - MimeType: emptyString, - Width: 0, - Height: 0, - HasPreviewImage: false, - MiniPreview: nil, - Content: "", - RemoteId: nil, - } + fileInfo := model.NewFileInfo(filename) + fileInfo.Id = getFileInfoID(createdFilename) + fileInfo.Path = filePath + fileInfo.Size = fileSize err := a.store.SaveFileInfo(fileInfo) if err != nil { return "", err } - return fullFilename, nil + return newFileName, nil } -func (a *App) GetFileInfo(filename string) (*mmModel.FileInfo, error) { +func (a *App) GetFileInfo(filename string) (*mm_model.FileInfo, error) { if len(filename) == 0 { return nil, errEmptyFilename } @@ -77,8 +58,7 @@ func (a *App) GetFileInfo(filename string) (*mmModel.FileInfo, error) { // filename is in the format 7. // we want to extract the part of this as this // will be the fileinfo id. - parts := strings.Split(filename, ".") - fileInfoID := parts[0][1:] + fileInfoID := getFileInfoID(strings.Split(filename, ".")[0]) fileInfo, err := a.store.GetFileInfo(fileInfoID) if err != nil { @@ -88,11 +68,36 @@ func (a *App) GetFileInfo(filename string) (*mmModel.FileInfo, error) { return fileInfo, nil } -func (a *App) GetFile(teamID, rootID, fileName string) (*mmModel.FileInfo, filestore.ReadCloseSeeker, error) { +func (a *App) GetFile(teamID, rootID, fileName string) (*mm_model.FileInfo, filestore.ReadCloseSeeker, error) { + fileInfo, filePath, err := a.GetFilePath(teamID, rootID, fileName) + if err != nil { + a.logger.Error("GetFile: Failed to GetFilePath.", mlog.String("Team", teamID), mlog.String("board", rootID), mlog.String("filename", fileName), mlog.Err(err)) + return nil, nil, err + } + + exists, err := a.filesBackend.FileExists(filePath) + if err != nil { + a.logger.Error("GetFile: Failed to check if file exists as path. ", mlog.String("Path", filePath), mlog.Err(err)) + return nil, nil, err + } + + if !exists { + return nil, nil, ErrFileNotFound + } + + reader, err := a.filesBackend.Reader(filePath) + if err != nil { + a.logger.Error("GetFile: Failed to get file reader of existing file at path", mlog.String("Path", filePath), mlog.Err(err)) + return nil, nil, err + } + + return fileInfo, reader, nil +} + +func (a *App) GetFilePath(teamID, rootID, fileName string) (*mm_model.FileInfo, string, error) { fileInfo, err := a.GetFileInfo(fileName) if err != nil && !model.IsErrNotFound(err) { - a.logger.Error("111") - return nil, nil, err + return nil, "", err } var filePath string @@ -103,23 +108,23 @@ func (a *App) GetFile(teamID, rootID, fileName string) (*mmModel.FileInfo, files filePath = filepath.Join(teamID, rootID, fileName) } - exists, err := a.filesBackend.FileExists(filePath) - if err != nil { - a.logger.Error(fmt.Sprintf("GetFile: Failed to check if file exists as path. Path: %s, error: %e", filePath, err)) - return nil, nil, err - } + return fileInfo, filePath, nil +} - if !exists { - return nil, nil, ErrFileNotFound +func getDestinationFilePath(isTemplate bool, teamID, boardID, filename string) string { + // if saving a file for a template, save using the "old method" that is /teamID/boardID/fileName + // this will prevent template files from being deleted by DataRetention, + // which deletes all files inside the "date" subdirectory + if isTemplate { + return filepath.Join(teamID, boardID, filename) } + return filepath.Join(utils.GetBaseFilePath(), filename) +} - reader, err := a.filesBackend.Reader(filePath) - if err != nil { - a.logger.Error(fmt.Sprintf("GetFile: Failed to get file reader of existing file at path: %s, error: %e", filePath, err)) - return nil, nil, err - } - - return fileInfo, reader, nil +func getFileInfoID(fileName string) string { + // Boards ids are 27 characters long with a prefix character. + // removing the prefix, returns the 26 character uuid + return fileName[1:] } func (a *App) GetFileReader(teamID, rootID, filename string) (filestore.ReadCloseSeeker, error) { @@ -175,3 +180,120 @@ func (a *App) MoveFile(channelID, teamID, boardID, filename string) error { } return nil } +func (a *App) CopyAndUpdateCardFiles(boardID, userID string, blocks []*model.Block, asTemplate bool) error { + newFileNames, err := a.CopyCardFiles(boardID, blocks, asTemplate) + if err != nil { + a.logger.Error("Could not copy files while duplicating board", mlog.String("BoardID", boardID), mlog.Err(err)) + } + + // blocks now has updated file ids for any blocks containing files. We need to update the database for them. + blockIDs := make([]string, 0) + blockPatches := make([]model.BlockPatch, 0) + for _, block := range blocks { + if block.Type == model.TypeImage || block.Type == model.TypeAttachment { + if fileID, ok := block.Fields["fileId"].(string); ok { + blockIDs = append(blockIDs, block.ID) + blockPatches = append(blockPatches, model.BlockPatch{ + UpdatedFields: map[string]interface{}{ + "fileId": newFileNames[fileID], + }, + DeletedFields: []string{"attachmentId"}, + }) + } + } + } + a.logger.Debug("Duplicate boards patching file IDs", mlog.Int("count", len(blockIDs))) + + if len(blockIDs) != 0 { + patches := &model.BlockPatchBatch{ + BlockIDs: blockIDs, + BlockPatches: blockPatches, + } + if err := a.store.PatchBlocks(patches, userID); err != nil { + return fmt.Errorf("could not patch file IDs while duplicating board %s: %w", boardID, err) + } + } + + return nil +} + +func (a *App) CopyCardFiles(sourceBoardID string, copiedBlocks []*model.Block, asTemplate bool) (map[string]string, error) { + // Images attached in cards have a path comprising the card's board ID. + // When we create a template from this board, we need to copy the files + // with the new board ID in path. + // Not doing so causing images in templates (and boards created from this + // template) to fail to load. + + // look up ID of source sourceBoard, which may be different than the blocks. + sourceBoard, err := a.GetBoard(sourceBoardID) + if err != nil || sourceBoard == nil { + return nil, fmt.Errorf("cannot fetch source board %s for CopyCardFiles: %w", sourceBoardID, err) + } + + var destBoard *model.Board + newFileNames := make(map[string]string) + for _, block := range copiedBlocks { + if block.Type != model.TypeImage && block.Type != model.TypeAttachment { + continue + } + + fileID, isOk := block.Fields["fileId"].(string) + if !isOk { + fileID, isOk = block.Fields["attachmentId"].(string) + if !isOk { + continue + } + } + + // create unique filename + ext := filepath.Ext(fileID) + fileInfoID := utils.NewID(utils.IDTypeNone) + destFilename := fileInfoID + ext + + if destBoard == nil || block.BoardID != destBoard.ID { + destBoard = sourceBoard + if block.BoardID != destBoard.ID { + destBoard, err = a.GetBoard(block.BoardID) + if err != nil { + return nil, fmt.Errorf("cannot fetch destination board %s for CopyCardFiles: %w", sourceBoardID, err) + } + } + } + + // GetFilePath will retrieve the correct path + // depending on whether FileInfo table is used for the file. + fileInfo, sourceFilePath, err := a.GetFilePath(sourceBoard.TeamID, sourceBoard.ID, fileID) + if err != nil { + return nil, fmt.Errorf("cannot fetch destination board %s for CopyCardFiles: %w", sourceBoardID, err) + } + destinationFilePath := getDestinationFilePath(asTemplate, destBoard.TeamID, destBoard.ID, destFilename) + + if fileInfo == nil { + fileInfo = model.NewFileInfo(destFilename) + } + fileInfo.Id = getFileInfoID(fileInfoID) + fileInfo.Path = destinationFilePath + err = a.store.SaveFileInfo(fileInfo) + if err != nil { + return nil, fmt.Errorf("CopyCardFiles: cannot create fileinfo: %w", err) + } + + a.logger.Debug( + "Copying card file", + mlog.String("sourceFilePath", sourceFilePath), + mlog.String("destinationFilePath", destinationFilePath), + ) + + if err := a.filesBackend.CopyFile(sourceFilePath, destinationFilePath); err != nil { + a.logger.Error( + "CopyCardFiles failed to copy file", + mlog.String("sourceFilePath", sourceFilePath), + mlog.String("destinationFilePath", destinationFilePath), + mlog.Err(err), + ) + } + newFileNames[fileID] = destFilename + } + + return newFileNames, nil +} diff --git a/server/app/files_test.go b/server/app/files_test.go index b39327f7b..73120b205 100644 --- a/server/app/files_test.go +++ b/server/app/files_test.go @@ -12,7 +12,8 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" - mmModel "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/focalboard/server/model" + mm_model "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/plugin/plugintest/mock" "github.com/mattermost/mattermost-server/v6/shared/filestore" "github.com/mattermost/mattermost-server/v6/shared/filestore/mocks" @@ -21,6 +22,7 @@ import ( const ( testFileName = "temp-file-name" testBoardID = "test-board-id" + testPath = "/path/to/file/fileName.txt" ) var errDummy = errors.New("hello") @@ -207,7 +209,7 @@ func TestSaveFile(t *testing.T) { } mockedFileBackend.On("WriteFile", mockedReadCloseSeek, mock.Anything).Return(writeFileFunc, writeFileErrorFunc) - actual, err := th.App.SaveFile(mockedReadCloseSeek, "1", testBoardID, fileName) + actual, err := th.App.SaveFile(mockedReadCloseSeek, "1", testBoardID, fileName, false) assert.Equal(t, fileName, actual) assert.Nil(t, err) }) @@ -231,7 +233,7 @@ func TestSaveFile(t *testing.T) { } mockedFileBackend.On("WriteFile", mockedReadCloseSeek, mock.Anything).Return(writeFileFunc, writeFileErrorFunc) - actual, err := th.App.SaveFile(mockedReadCloseSeek, "1", "test-board-id", fileName) + actual, err := th.App.SaveFile(mockedReadCloseSeek, "1", "test-board-id", fileName, false) assert.Nil(t, err) assert.NotNil(t, actual) }) @@ -255,7 +257,7 @@ func TestSaveFile(t *testing.T) { } mockedFileBackend.On("WriteFile", mockedReadCloseSeek, mock.Anything).Return(writeFileFunc, writeFileErrorFunc) - actual, err := th.App.SaveFile(mockedReadCloseSeek, "1", "test-board-id", fileName) + actual, err := th.App.SaveFile(mockedReadCloseSeek, "1", "test-board-id", fileName, false) assert.Equal(t, "", actual) assert.Equal(t, "unable to store the file in the files storage: Mocked File backend error", err.Error()) }) @@ -265,7 +267,7 @@ func TestGetFileInfo(t *testing.T) { th, _ := SetupTestHelper(t) t.Run("should return file info", func(t *testing.T) { - fileInfo := &mmModel.FileInfo{ + fileInfo := &mm_model.FileInfo{ Id: "file_info_id", Archived: false, } @@ -284,7 +286,7 @@ func TestGetFileInfo(t *testing.T) { }) t.Run("should return archived file info", func(t *testing.T) { - fileInfo := &mmModel.FileInfo{ + fileInfo := &mm_model.FileInfo{ Id: "file_info_id", Archived: true, } @@ -308,11 +310,10 @@ func TestGetFileInfo(t *testing.T) { func TestGetFile(t *testing.T) { th, _ := SetupTestHelper(t) - - t.Run("when FileInfo exists", func(t *testing.T) { - th.Store.EXPECT().GetFileInfo("fileInfoID").Return(&mmModel.FileInfo{ + t.Run("happy path, no errors", func(t *testing.T) { + th.Store.EXPECT().GetFileInfo("fileInfoID").Return(&mm_model.FileInfo{ Id: "fileInfoID", - Path: "/path/to/file/fileName.txt", + Path: testPath, }, nil) mockedFileBackend := &mocks.FileBackend{} @@ -325,8 +326,8 @@ func TestGetFile(t *testing.T) { readerErrorFunc := func(path string) error { return nil } - mockedFileBackend.On("Reader", "/path/to/file/fileName.txt").Return(readerFunc, readerErrorFunc) - mockedFileBackend.On("FileExists", "/path/to/file/fileName.txt").Return(true, nil) + mockedFileBackend.On("Reader", testPath).Return(readerFunc, readerErrorFunc) + mockedFileBackend.On("FileExists", testPath).Return(true, nil) fileInfo, seeker, err := th.App.GetFile("teamID", "boardID", "7fileInfoID.txt") assert.NoError(t, err) @@ -334,51 +335,222 @@ func TestGetFile(t *testing.T) { assert.NotNil(t, seeker) }) + t.Run("when GetFilePath() throws error", func(t *testing.T) { + th.Store.EXPECT().GetFileInfo("fileInfoID").Return(nil, errDummy) + + fileInfo, seeker, err := th.App.GetFile("teamID", "boardID", "7fileInfoID.txt") + assert.Error(t, err) + assert.Nil(t, fileInfo) + assert.Nil(t, seeker) + }) + + t.Run("when FileExists returns false", func(t *testing.T) { + th.Store.EXPECT().GetFileInfo("fileInfoID").Return(&mm_model.FileInfo{ + Id: "fileInfoID", + Path: testPath, + }, nil) + + mockedFileBackend := &mocks.FileBackend{} + th.App.filesBackend = mockedFileBackend + mockedFileBackend.On("FileExists", testPath).Return(false, nil) + + fileInfo, seeker, err := th.App.GetFile("teamID", "boardID", "7fileInfoID.txt") + assert.Error(t, err) + assert.Nil(t, fileInfo) + assert.Nil(t, seeker) + }) + t.Run("when FileReader throws error", func(t *testing.T) { + th.Store.EXPECT().GetFileInfo("fileInfoID").Return(&mm_model.FileInfo{ + Id: "fileInfoID", + Path: testPath, + }, nil) + + mockedFileBackend := &mocks.FileBackend{} + th.App.filesBackend = mockedFileBackend + mockedFileBackend.On("Reader", testPath).Return(nil, errDummy) + mockedFileBackend.On("FileExists", testPath).Return(true, nil) + + fileInfo, seeker, err := th.App.GetFile("teamID", "boardID", "7fileInfoID.txt") + assert.Error(t, err) + assert.Nil(t, fileInfo) + assert.Nil(t, seeker) + }) +} + +func TestGetFilePath(t *testing.T) { + th, _ := SetupTestHelper(t) + + t.Run("when FileInfo exists", func(t *testing.T) { + th.Store.EXPECT().GetFileInfo("fileInfoID").Return(&mm_model.FileInfo{ + Id: "fileInfoID", + Path: testPath, + }, nil) + + fileInfo, filePath, err := th.App.GetFilePath("teamID", "boardID", "7fileInfoID.txt") + assert.NoError(t, err) + assert.NotNil(t, fileInfo) + assert.Equal(t, testPath, filePath) + }) + t.Run("when FileInfo doesn't exist", func(t *testing.T) { th.Store.EXPECT().GetFileInfo("fileInfoID").Return(nil, nil) - mockedFileBackend := &mocks.FileBackend{} - th.App.filesBackend = mockedFileBackend - mockedReadCloseSeek := &mocks.ReadCloseSeeker{} - readerFunc := func(path string) filestore.ReadCloseSeeker { - return mockedReadCloseSeek - } - - readerErrorFunc := func(path string) error { - return nil - } - - mockedFileBackend.On("Reader", "teamID/boardID/7fileInfoID.txt").Return(readerFunc, readerErrorFunc) - mockedFileBackend.On("FileExists", "teamID/boardID/7fileInfoID.txt").Return(true, nil) - - fileInfo, seeker, err := th.App.GetFile("teamID", "boardID", "7fileInfoID.txt") + fileInfo, filePath, err := th.App.GetFilePath("teamID", "boardID", "7fileInfoID.txt") assert.NoError(t, err) assert.Nil(t, fileInfo) - assert.NotNil(t, seeker) + assert.Equal(t, "teamID/boardID/7fileInfoID.txt", filePath) }) t.Run("when FileInfo exists but FileInfo.Path is not set", func(t *testing.T) { - th.Store.EXPECT().GetFileInfo("fileInfoID").Return(&mmModel.FileInfo{ + th.Store.EXPECT().GetFileInfo("fileInfoID").Return(&mm_model.FileInfo{ Id: "fileInfoID", Path: "", }, nil) - mockedFileBackend := &mocks.FileBackend{} - th.App.filesBackend = mockedFileBackend - mockedReadCloseSeek := &mocks.ReadCloseSeeker{} - readerFunc := func(path string) filestore.ReadCloseSeeker { - return mockedReadCloseSeek - } - - readerErrorFunc := func(path string) error { - return nil - } - mockedFileBackend.On("Reader", "teamID/boardID/7fileInfoID.txt").Return(readerFunc, readerErrorFunc) - mockedFileBackend.On("FileExists", "teamID/boardID/7fileInfoID.txt").Return(true, nil) - - fileInfo, seeker, err := th.App.GetFile("teamID", "boardID", "7fileInfoID.txt") + fileInfo, filePath, err := th.App.GetFilePath("teamID", "boardID", "7fileInfoID.txt") assert.NoError(t, err) assert.NotNil(t, fileInfo) - assert.NotNil(t, seeker) + assert.Equal(t, "teamID/boardID/7fileInfoID.txt", filePath) + }) +} + +func TestCopyCard(t *testing.T) { + th, _ := SetupTestHelper(t) + imageBlock := &model.Block{ + ID: "imageBlock", + ParentID: "c3zqnh6fsu3f4mr6hzq9hizwske", + CreatedBy: "6k6ynxdp47dujjhhojw9nqhmyh", + ModifiedBy: "6k6ynxdp47dujjhhojw9nqhmyh", + Schema: 1, + Type: "image", + Title: "", + Fields: map[string]interface{}{"fileId": "7fileName.jpg"}, + CreateAt: 1680725585250, + UpdateAt: 1680725585250, + DeleteAt: 0, + BoardID: "boardID", + } + t.Run("Board doesn't exist", func(t *testing.T) { + th.Store.EXPECT().GetBoard("boardID").Return(nil, errDummy) + _, err := th.App.CopyCardFiles("boardID", []*model.Block{}, false) + assert.Error(t, err) + }) + + t.Run("Board exists, image block, with FileInfo", func(t *testing.T) { + fileInfo := &mm_model.FileInfo{ + Id: "imageBlock", + Path: testPath, + } + th.Store.EXPECT().GetBoard("boardID").Return(&model.Board{ + ID: "boardID", + IsTemplate: false, + }, nil) + th.Store.EXPECT().GetFileInfo("fileName").Return(fileInfo, nil) + th.Store.EXPECT().SaveFileInfo(fileInfo).Return(nil) + + mockedFileBackend := &mocks.FileBackend{} + th.App.filesBackend = mockedFileBackend + mockedFileBackend.On("CopyFile", mock.Anything, mock.Anything).Return(nil) + + updatedFileNames, err := th.App.CopyCardFiles("boardID", []*model.Block{imageBlock}, false) + assert.NoError(t, err) + assert.Equal(t, "7fileName.jpg", imageBlock.Fields["fileId"]) + assert.NotNil(t, updatedFileNames["7fileName.jpg"]) + assert.NotNil(t, updatedFileNames[imageBlock.Fields["fileId"].(string)]) + }) + + t.Run("Board exists, attachment block, with FileInfo", func(t *testing.T) { + attachmentBlock := &model.Block{ + ID: "attachmentBlock", + ParentID: "c3zqnh6fsu3f4mr6hzq9hizwske", + CreatedBy: "6k6ynxdp47dujjhhojw9nqhmyh", + ModifiedBy: "6k6ynxdp47dujjhhojw9nqhmyh", + Schema: 1, + Type: "attachment", + Title: "", + Fields: map[string]interface{}{"fileId": "7fileName.jpg"}, + CreateAt: 1680725585250, + UpdateAt: 1680725585250, + DeleteAt: 0, + BoardID: "boardID", + } + + fileInfo := &mm_model.FileInfo{ + Id: "attachmentBlock", + Path: testPath, + } + th.Store.EXPECT().GetBoard("boardID").Return(&model.Board{ + ID: "boardID", + IsTemplate: false, + }, nil) + th.Store.EXPECT().GetFileInfo("fileName").Return(fileInfo, nil) + th.Store.EXPECT().SaveFileInfo(fileInfo).Return(nil) + + mockedFileBackend := &mocks.FileBackend{} + th.App.filesBackend = mockedFileBackend + mockedFileBackend.On("CopyFile", mock.Anything, mock.Anything).Return(nil) + + updatedFileNames, err := th.App.CopyCardFiles("boardID", []*model.Block{attachmentBlock}, false) + assert.NoError(t, err) + assert.NotNil(t, updatedFileNames[imageBlock.Fields["fileId"].(string)]) + }) + + t.Run("Board exists, image block, without FileInfo", func(t *testing.T) { + th.Store.EXPECT().GetBoard("boardID").Return(&model.Board{ + ID: "boardID", + IsTemplate: false, + }, nil) + th.Store.EXPECT().GetFileInfo(gomock.Any()).Return(nil, nil) + th.Store.EXPECT().SaveFileInfo(gomock.Any()).Return(nil) + + mockedFileBackend := &mocks.FileBackend{} + th.App.filesBackend = mockedFileBackend + mockedFileBackend.On("CopyFile", mock.Anything, mock.Anything).Return(nil) + + updatedFileNames, err := th.App.CopyCardFiles("boardID", []*model.Block{imageBlock}, false) + assert.NoError(t, err) + assert.NotNil(t, imageBlock.Fields["fileId"].(string)) + assert.NotNil(t, updatedFileNames[imageBlock.Fields["fileId"].(string)]) + }) +} + +func TestCopyAndUpdateCardFiles(t *testing.T) { + th, _ := SetupTestHelper(t) + imageBlock := &model.Block{ + ID: "imageBlock", + ParentID: "c3zqnh6fsu3f4mr6hzq9hizwske", + CreatedBy: "6k6ynxdp47dujjhhojw9nqhmyh", + ModifiedBy: "6k6ynxdp47dujjhhojw9nqhmyh", + Schema: 1, + Type: "image", + Title: "", + Fields: map[string]interface{}{"fileId": "7fileName.jpg"}, + CreateAt: 1680725585250, + UpdateAt: 1680725585250, + DeleteAt: 0, + BoardID: "boardID", + } + + t.Run("Board exists, image block, with FileInfo", func(t *testing.T) { + fileInfo := &mm_model.FileInfo{ + Id: "imageBlock", + Path: testPath, + } + th.Store.EXPECT().GetBoard("boardID").Return(&model.Board{ + ID: "boardID", + IsTemplate: false, + }, nil) + th.Store.EXPECT().GetFileInfo("fileName").Return(fileInfo, nil) + th.Store.EXPECT().SaveFileInfo(fileInfo).Return(nil) + th.Store.EXPECT().PatchBlocks(gomock.Any(), "userID").Return(nil) + + mockedFileBackend := &mocks.FileBackend{} + th.App.filesBackend = mockedFileBackend + mockedFileBackend.On("CopyFile", mock.Anything, mock.Anything).Return(nil) + + err := th.App.CopyAndUpdateCardFiles("boardID", "userID", []*model.Block{imageBlock}, false) + assert.NoError(t, err) + + assert.NotEqual(t, testPath, imageBlock.Fields["fileId"]) }) } diff --git a/server/app/import.go b/server/app/import.go index 6dc68d9c9..7ea99cd87 100644 --- a/server/app/import.go +++ b/server/app/import.go @@ -41,27 +41,19 @@ func (a *App) ImportArchive(r io.Reader, opt model.ImportArchiveOptions) error { a.logger.Debug("importing legacy archive") _, errImport := a.ImportBoardJSONL(br, opt) - go func() { - if err := a.UpdateCardLimitTimestamp(); err != nil { - a.logger.Error( - "UpdateCardLimitTimestamp failed after importing a legacy file", - mlog.Err(err), - ) - } - }() - return errImport } - a.logger.Debug("importing archive") zr := zipstream.NewReader(br) - boardMap := make(map[string]string) // maps old board ids to new + boardMap := make(map[string]*model.Board) // maps old board ids to new + fileMap := make(map[string]string) // maps old fileIds to new for { hdr, err := zr.Next() if err != nil { if errors.Is(err, io.EOF) { + a.fixImagesAttachments(boardMap, fileMap, opt.TeamID, opt.ModifiedBy) a.logger.Debug("import archive - done", mlog.Int("boards_imported", len(boardMap))) return nil } @@ -81,14 +73,14 @@ func (a *App) ImportArchive(r io.Reader, opt model.ImportArchiveOptions) error { return model.NewErrUnsupportedArchiveVersion(ver, archiveVersion) } case "board.jsonl": - boardID, err := a.ImportBoardJSONL(zr, opt) + board, err := a.ImportBoardJSONL(zr, opt) if err != nil { return fmt.Errorf("cannot import board %s: %w", dir, err) } - boardMap[dir] = boardID + boardMap[dir] = board default: // import file/image; dir is the old board id - boardID, ok := boardMap[dir] + board, ok := boardMap[dir] if !ok { a.logger.Warn("skipping orphan image in archive", mlog.String("dir", dir), @@ -96,33 +88,65 @@ func (a *App) ImportArchive(r io.Reader, opt model.ImportArchiveOptions) error { ) continue } - // save file with original filename so it matches name in image block. - filePath := filepath.Join(opt.TeamID, boardID, filename) - _, err := a.filesBackend.WriteFile(zr, filePath) + newFileName, err := a.SaveFile(zr, opt.TeamID, board.ID, filename, board.IsTemplate) if err != nil { return fmt.Errorf("cannot import file %s for board %s: %w", filename, dir, err) } + fileMap[filename] = newFileName + + a.logger.Debug("import archive file", + mlog.String("TeamID", opt.TeamID), + mlog.String("boardID", board.ID), + mlog.String("filename", filename), + mlog.String("newFileName", newFileName), + ) + } + } +} + +// Update image and attachment blocks. +func (a *App) fixImagesAttachments(boardMap map[string]*model.Board, fileMap map[string]string, teamID string, userID string) { + blockIDs := make([]string, 0) + blockPatches := make([]model.BlockPatch, 0) + for _, board := range boardMap { + if board.IsTemplate { + continue } - a.logger.Trace("import archive file", - mlog.String("dir", dir), - mlog.String("filename", filename), - ) + opts := model.QueryBlocksOptions{ + BoardID: board.ID, + } + newBlocks, err := a.store.GetBlocks(opts) + if err != nil { + a.logger.Info("cannot retrieve imported blocks for board", mlog.String("BoardID", board.ID), mlog.Err(err)) + return + } - go func() { - if err := a.UpdateCardLimitTimestamp(); err != nil { - a.logger.Error( - "UpdateCardLimitTimestamp failed after importing an archive", - mlog.Err(err), - ) + for _, block := range newBlocks { + if block.Type == "image" || block.Type == "attachment" { + fieldName := "fileId" + oldID := block.Fields[fieldName] + blockIDs = append(blockIDs, block.ID) + + blockPatches = append(blockPatches, model.BlockPatch{ + UpdatedFields: map[string]interface{}{ + fieldName: fileMap[oldID.(string)], + }, + }) } - }() + } + + blockPatchBatch := model.BlockPatchBatch{BlockIDs: blockIDs, BlockPatches: blockPatches} + err = a.PatchBlocks(teamID, &blockPatchBatch, userID) + if err != nil { + a.logger.Info("Error patching blocks for image import", mlog.Err(err)) + } } } // ImportBoardJSONL imports a JSONL file containing blocks for one board. The resulting // board id is returned. -func (a *App) ImportBoardJSONL(r io.Reader, opt model.ImportArchiveOptions) (string, error) { +func (a *App) ImportBoardJSONL(r io.Reader, opt model.ImportArchiveOptions) (*model.Board, error) { // TODO: Stream this once `model.GenerateBlockIDs` can take a stream of blocks. // We don't want to load the whole file in memory, even though it's a single board. boardsAndBlocks := &model.BoardsAndBlocks{ @@ -155,7 +179,7 @@ func (a *App) ImportBoardJSONL(r io.Reader, opt model.ImportArchiveOptions) (str if !skip { var archiveLine model.ArchiveLine if err := json.Unmarshal(line, &archiveLine); err != nil { - return "", fmt.Errorf("error parsing archive line %d: %w", lineNum, err) + return nil, fmt.Errorf("error parsing archive line %d: %w", lineNum, err) } // first line must be a board @@ -167,7 +191,7 @@ func (a *App) ImportBoardJSONL(r io.Reader, opt model.ImportArchiveOptions) (str case "board": var board model.Board if err2 := json.Unmarshal(archiveLine.Data, &board); err2 != nil { - return "", fmt.Errorf("invalid board in archive line %d: %w", lineNum, err2) + return nil, fmt.Errorf("invalid board in archive line %d: %w", lineNum, err2) } board.ModifiedBy = userID board.UpdateAt = now @@ -178,20 +202,20 @@ func (a *App) ImportBoardJSONL(r io.Reader, opt model.ImportArchiveOptions) (str // legacy archives encoded boards as blocks; we need to convert them to real boards. var block *model.Block if err2 := json.Unmarshal(archiveLine.Data, &block); err2 != nil { - return "", fmt.Errorf("invalid board block in archive line %d: %w", lineNum, err2) + return nil, fmt.Errorf("invalid board block in archive line %d: %w", lineNum, err2) } block.ModifiedBy = userID block.UpdateAt = now board, err := a.blockToBoard(block, opt) if err != nil { - return "", fmt.Errorf("cannot convert archive line %d to block: %w", lineNum, err) + return nil, fmt.Errorf("cannot convert archive line %d to block: %w", lineNum, err) } boardsAndBlocks.Boards = append(boardsAndBlocks.Boards, board) boardID = board.ID case "block": var block *model.Block if err2 := json.Unmarshal(archiveLine.Data, &block); err2 != nil { - return "", fmt.Errorf("invalid block in archive line %d: %w", lineNum, err2) + return nil, fmt.Errorf("invalid block in archive line %d: %w", lineNum, err2) } block.ModifiedBy = userID block.UpdateAt = now @@ -200,11 +224,11 @@ func (a *App) ImportBoardJSONL(r io.Reader, opt model.ImportArchiveOptions) (str case "boardMember": var boardMember *model.BoardMember if err2 := json.Unmarshal(archiveLine.Data, &boardMember); err2 != nil { - return "", fmt.Errorf("invalid board Member in archive line %d: %w", lineNum, err2) + return nil, fmt.Errorf("invalid board Member in archive line %d: %w", lineNum, err2) } boardMembers = append(boardMembers, boardMember) default: - return "", model.NewErrUnsupportedArchiveLineType(lineNum, archiveLine.Type) + return nil, model.NewErrUnsupportedArchiveLineType(lineNum, archiveLine.Type) } firstLine = false } @@ -214,7 +238,7 @@ func (a *App) ImportBoardJSONL(r io.Reader, opt model.ImportArchiveOptions) (str if errors.Is(errRead, io.EOF) { break } - return "", fmt.Errorf("error reading archive line %d: %w", lineNum, errRead) + return nil, fmt.Errorf("error reading archive line %d: %w", lineNum, errRead) } lineNum++ } @@ -231,12 +255,12 @@ func (a *App) ImportBoardJSONL(r io.Reader, opt model.ImportArchiveOptions) (str var err error boardsAndBlocks, err = model.GenerateBoardsAndBlocksIDs(boardsAndBlocks, a.logger) if err != nil { - return "", fmt.Errorf("error generating archive block IDs: %w", err) + return nil, fmt.Errorf("error generating archive block IDs: %w", err) } boardsAndBlocks, err = a.CreateBoardsAndBlocks(boardsAndBlocks, opt.ModifiedBy, false) if err != nil { - return "", fmt.Errorf("error inserting archive blocks: %w", err) + return nil, fmt.Errorf("error inserting archive blocks: %w", err) } // add users to all the new boards (if not the fake system user). @@ -248,7 +272,7 @@ func (a *App) ImportBoardJSONL(r io.Reader, opt model.ImportArchiveOptions) (str SchemeAdmin: true, } if _, err2 := a.AddMemberToBoard(adminMember); err2 != nil { - return "", fmt.Errorf("cannot add adminMember to board: %w", err2) + return nil, fmt.Errorf("cannot add adminMember to board: %w", err2) } for _, boardMember := range boardMembers { bm := &model.BoardMember{ @@ -263,16 +287,16 @@ func (a *App) ImportBoardJSONL(r io.Reader, opt model.ImportArchiveOptions) (str Synthetic: boardMember.Synthetic, } if _, err2 := a.AddMemberToBoard(bm); err2 != nil { - return "", fmt.Errorf("cannot add member to board: %w", err2) + return nil, fmt.Errorf("cannot add member to board: %w", err2) } } } // find new board id for _, board := range boardsAndBlocks.Boards { - return board.ID, nil + return board, nil } - return "", fmt.Errorf("missing board in archive: %w", model.ErrInvalidBoardBlock) + return nil, fmt.Errorf("missing board in archive: %w", model.ErrInvalidBoardBlock) } // fixBoardsandBlocks allows the caller of `ImportArchive` to modify or filters boards and blocks being diff --git a/server/app/import_test.go b/server/app/import_test.go index 4755f8254..46cd77608 100644 --- a/server/app/import_test.go +++ b/server/app/import_test.go @@ -134,9 +134,76 @@ func TestApp_ImportArchive(t *testing.T) { th.Store.EXPECT().GetUserByID("hxxzooc3ff8cubsgtcmpn8733e").AnyTimes().Return(user2, nil) th.Store.EXPECT().GetUserByID("nto73edn5ir6ifimo5a53y1dwa").AnyTimes().Return(user3, nil) - boardID, err := th.App.ImportBoardJSONL(r, opts) - require.Equal(t, board.ID, boardID, "Board ID should be same") + newBoard, err := th.App.ImportBoardJSONL(r, opts) require.NoError(t, err, "import archive should not fail") + require.Equal(t, board.ID, newBoard.ID, "Board ID should be same") + }) + + t.Run("fix image and attachment", func(t *testing.T) { + boardMap := map[string]*model.Board{ + "test": board, + } + + fileMap := map[string]string{ + "oldFileName1.jpg": "newFileName1.jpg", + "oldFileName2.jpg": "newFileName2.jpg", + } + + imageBlock := &model.Block{ + ID: "blockID-1", + ParentID: "c3zqnh6fsu3f4mr6hzq9hizwske", + CreatedBy: "6k6ynxdp47dujjhhojw9nqhmyh", + ModifiedBy: "6k6ynxdp47dujjhhojw9nqhmyh", + Schema: 1, + Type: "image", + Title: "", + Fields: map[string]interface{}{"fileId": "oldFileName1.jpg"}, + CreateAt: 1680725585250, + UpdateAt: 1680725585250, + DeleteAt: 0, + BoardID: "board-id", + } + + attachmentBlock := &model.Block{ + ID: "blockID-2", + ParentID: "c3zqnh6fsu3f4mr6hzq9hizwske", + CreatedBy: "6k6ynxdp47dujjhhojw9nqhmyh", + ModifiedBy: "6k6ynxdp47dujjhhojw9nqhmyh", + Schema: 1, + Type: "attachment", + Title: "", + Fields: map[string]interface{}{"fileId": "oldFileName2.jpg"}, + CreateAt: 1680725585250, + UpdateAt: 1680725585250, + DeleteAt: 0, + BoardID: "board-id", + } + + blockIDs := []string{"blockID-1", "blockID-2"} + + blockPatch := model.BlockPatch{ + UpdatedFields: map[string]interface{}{"fileId": "newFileName1.jpg"}, + } + + blockPatch2 := model.BlockPatch{ + UpdatedFields: map[string]interface{}{"fileId": "newFileName2.jpg"}, + } + + blockPatches := []model.BlockPatch{blockPatch, blockPatch2} + + blockPatchesBatch := model.BlockPatchBatch{BlockIDs: blockIDs, BlockPatches: blockPatches} + + opts := model.QueryBlocksOptions{ + BoardID: board.ID, + } + th.Store.EXPECT().GetBlocks(opts).Return([]*model.Block{imageBlock, attachmentBlock}, nil) + th.Store.EXPECT().GetBlocksByIDs(blockIDs).Return([]*model.Block{imageBlock, attachmentBlock}, nil) + th.Store.EXPECT().GetBlock(blockIDs[0]).Return(imageBlock, nil) + th.Store.EXPECT().GetBlock(blockIDs[1]).Return(attachmentBlock, nil) + th.Store.EXPECT().GetMembersForBoard("board-id").AnyTimes().Return([]*model.BoardMember{}, nil) + + th.Store.EXPECT().PatchBlocks(&blockPatchesBatch, "my-userid") + th.App.fixImagesAttachments(boardMap, fileMap, "test-team", "my-userid") }) } diff --git a/server/app/templates_test.go b/server/app/templates_test.go index 9a1105d17..d30eff93e 100644 --- a/server/app/templates_test.go +++ b/server/app/templates_test.go @@ -49,6 +49,7 @@ func TestApp_initializeTemplates(t *testing.T) { th.Store.EXPECT().GetMembersForBoard(board.ID).AnyTimes().Return([]*model.BoardMember{}, nil) th.Store.EXPECT().GetBoard(board.ID).AnyTimes().Return(board, nil) th.Store.EXPECT().GetMemberForBoard(gomock.Any(), gomock.Any()).AnyTimes().Return(boardMember, nil) + th.Store.EXPECT().SaveFileInfo(gomock.Any()).Return(nil).AnyTimes() th.FilesBackend.On("WriteFile", mock.Anything, mock.Anything).Return(int64(1), nil) diff --git a/server/integrationtests/permissions_test.go b/server/integrationtests/permissions_test.go index 323ed7a3a..95b5a4727 100644 --- a/server/integrationtests/permissions_test.go +++ b/server/integrationtests/permissions_test.go @@ -3375,7 +3375,7 @@ func TestPermissionsGetFile(t *testing.T) { clients := setupClients(th) testData := setupData(t, th) - newFileID, err := th.Server.App().SaveFile(bytes.NewBuffer([]byte("test")), "test-team", testData.privateBoard.ID, "test.png") + newFileID, err := th.Server.App().SaveFile(bytes.NewBuffer([]byte("test")), "test-team", testData.privateBoard.ID, "test.png", false) require.NoError(t, err) ttCases := ttCasesF() @@ -3390,7 +3390,7 @@ func TestPermissionsGetFile(t *testing.T) { clients := setupLocalClients(th) testData := setupData(t, th) - newFileID, err := th.Server.App().SaveFile(bytes.NewBuffer([]byte("test")), "test-team", testData.privateBoard.ID, "test.png") + newFileID, err := th.Server.App().SaveFile(bytes.NewBuffer([]byte("test")), "test-team", testData.privateBoard.ID, "test.png", false) require.NoError(t, err) ttCases := ttCasesF() diff --git a/server/model/file.go b/server/model/file.go new file mode 100644 index 000000000..a2d435666 --- /dev/null +++ b/server/model/file.go @@ -0,0 +1,25 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. +package model + +import ( + "mime" + "path/filepath" + "strings" + + "github.com/mattermost/focalboard/server/utils" + mm_model "github.com/mattermost/mattermost-server/v6/model" +) + +func NewFileInfo(name string) *mm_model.FileInfo { + extension := strings.ToLower(filepath.Ext(name)) + now := utils.GetMillis() + return &mm_model.FileInfo{ + CreatorId: "boards", + CreateAt: now, + UpdateAt: now, + Name: name, + Extension: extension, + MimeType: mime.TypeByExtension(extension), + } +} diff --git a/webapp/src/blocks/attachmentBlock.tsx b/webapp/src/blocks/attachmentBlock.tsx index bf0568505..f84e6d051 100644 --- a/webapp/src/blocks/attachmentBlock.tsx +++ b/webapp/src/blocks/attachmentBlock.tsx @@ -3,7 +3,7 @@ import {Block, createBlock} from './block' type AttachmentBlockFields = { - attachmentId: string + fileId: string } type AttachmentBlock = Block & { @@ -18,7 +18,7 @@ function createAttachmentBlock(block?: Block): AttachmentBlock { ...createBlock(block), type: 'attachment', fields: { - attachmentId: block?.fields.attachmentId || '', + fileId: block?.fields.attachmentId || block?.fields.fileId || '', }, isUploading: false, uploadingPercent: 0, diff --git a/webapp/src/components/cardDialog.tsx b/webapp/src/components/cardDialog.tsx index da13e035d..ec484e668 100644 --- a/webapp/src/components/cardDialog.tsx +++ b/webapp/src/components/cardDialog.tsx @@ -151,7 +151,7 @@ const CardDialog = (props: Props): JSX.Element => { Utils.selectLocalFile(async (attachment) => { const uploadingBlock = createBlock() uploadingBlock.title = attachment.name - uploadingBlock.fields.attachmentId = attachment.name + uploadingBlock.fields.fileId = attachment.name uploadingBlock.boardId = boardId if (card) { uploadingBlock.parentId = card.id @@ -177,11 +177,11 @@ const CardDialog = (props: Props): JSX.Element => { xhr.onload = () => { if (xhr.status === 200 && xhr.readyState === 4) { const json = JSON.parse(xhr.response) - const attachmentId = json.fileId - if (attachmentId) { + const fileId = json.fileId + if (fileId) { removeUploadingAttachment(uploadingBlock) const block = createAttachmentBlock() - block.fields.attachmentId = attachmentId || '' + block.fields.fileId = fileId || '' block.title = attachment.name sendFlashMessage({content: intl.formatMessage({id: 'AttachmentBlock.uploadSuccess', defaultMessage: 'Attachment uploaded successfull.'}), severity: 'normal'}) resolve(block) diff --git a/webapp/src/components/content/attachmentElement.test.tsx b/webapp/src/components/content/attachmentElement.test.tsx index 4a9ab2af2..084f39e08 100644 --- a/webapp/src/components/content/attachmentElement.test.tsx +++ b/webapp/src/components/content/attachmentElement.test.tsx @@ -39,7 +39,7 @@ describe('component/content/FileBlock', () => { type: 'attachment', title: 'test-title', fields: { - attachmentId: 'test.txt', + fileId: 'test.txt', }, createdBy: 'test-user-id', createAt: 0, diff --git a/webapp/src/components/content/attachmentElement.tsx b/webapp/src/components/content/attachmentElement.tsx index 72a51a8a2..1df41dd6c 100644 --- a/webapp/src/components/content/attachmentElement.tsx +++ b/webapp/src/components/content/attachmentElement.tsx @@ -50,7 +50,7 @@ const AttachmentElement = (props: Props): JSX.Element|null => { }) return } - const attachmentInfo = await octoClient.getFileInfo(block.boardId, block.fields.attachmentId) + const attachmentInfo = await octoClient.getFileInfo(block.boardId, block.fields.fileId) setFileInfo(attachmentInfo) } loadFile() @@ -113,7 +113,7 @@ const AttachmentElement = (props: Props): JSX.Element|null => { } const attachmentDownloadHandler = async () => { - const attachment = await octoClient.getFileAsDataUrl(block.boardId, block.fields.attachmentId) + const attachment = await octoClient.getFileAsDataUrl(block.boardId, block.fields.fileId) const anchor = document.createElement('a') anchor.href = attachment.url || '' anchor.download = fileInfo.name || '' From c3b1c82b1a6727c6eb69c611c6316cc555bc0f9a Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Wed, 31 May 2023 07:26:19 -0700 Subject: [PATCH 056/102] Fix cards not deleting properly. (#4746) * Fix cards not deleting properly. * Review feedback * Test and lint fixes. * Fix tests. --- mattermost-plugin/server/manifest.go | 3 +- server/app/blocks.go | 15 ----- server/services/store/sqlstore/blocks.go | 70 ++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/mattermost-plugin/server/manifest.go b/mattermost-plugin/server/manifest.go index 615e216f5..ea3af5430 100644 --- a/mattermost-plugin/server/manifest.go +++ b/mattermost-plugin/server/manifest.go @@ -45,7 +45,8 @@ const manifestStr = ` "type": "bool", "help_text": "This allows board editors to share boards that can be accessed by anyone with the link.", "placeholder": "", - "default": false + "default": false, + "hosting": "" } ] } diff --git a/server/app/blocks.go b/server/app/blocks.go index 41fd233a8..65a2628fc 100644 --- a/server/app/blocks.go +++ b/server/app/blocks.go @@ -3,7 +3,6 @@ package app import ( "errors" "fmt" - "path/filepath" "github.com/mattermost/focalboard/server/model" "github.com/mattermost/focalboard/server/services/notify" @@ -324,20 +323,6 @@ func (a *App) DeleteBlockAndNotify(blockID string, modifiedBy string, disableNot return err } - if block.Type == model.TypeImage { - fileName, fileIDExists := block.Fields["fileId"] - if fileName, fileIDIsString := fileName.(string); fileIDExists && fileIDIsString { - filePath := filepath.Join(block.BoardID, fileName) - err = a.filesBackend.RemoveFile(filePath) - - if err != nil { - a.logger.Error("Error deleting image file", - mlog.String("FilePath", filePath), - mlog.Err(err)) - } - } - } - a.blockChangeNotifier.Enqueue(func() error { a.wsAdapter.BroadcastBlockDelete(board.TeamID, blockID, block.BoardID) a.metrics.IncrementBlocksDeleted(1) diff --git a/server/services/store/sqlstore/blocks.go b/server/services/store/sqlstore/blocks.go index 69b650af6..306815a18 100644 --- a/server/services/store/sqlstore/blocks.go +++ b/server/services/store/sqlstore/blocks.go @@ -365,6 +365,14 @@ func (s *SQLStore) deleteBlock(db sq.BaseRunner, blockID string, modifiedBy stri return s.deleteBlockAndChildren(db, blockID, modifiedBy, false) } +func retrieveFileIDFromBlockFieldStorage(id string) string { + parts := strings.Split(id, ".") + if len(parts) < 1 { + return "" + } + return parts[0][1:] +} + func (s *SQLStore) deleteBlockAndChildren(db sq.BaseRunner, blockID string, modifiedBy string, keepChildren bool) error { block, err := s.getBlock(db, blockID) if model.IsErrNotFound(err) { @@ -415,6 +423,30 @@ func (s *SQLStore) deleteBlockAndChildren(db sq.BaseRunner, blockID string, modi return err } + // fileId and attachmentId shoudn't exist at the same time + fileID := "" + fileIDWithExtention, fileIDExists := block.Fields["fileId"] + if fileIDExists { + fileID = retrieveFileIDFromBlockFieldStorage(fileIDWithExtention.(string)) + } + + if fileID == "" { + attachmentIDWithExtention, attachmentIDExists := block.Fields["attachmentId"] + if attachmentIDExists { + fileID = retrieveFileIDFromBlockFieldStorage(attachmentIDWithExtention.(string)) + } + } + + if fileID != "" { + deleteFileInfoQuery := s.getQueryBuilder(db). + Update("FileInfo"). + Set("DeleteAt", model.GetMillis()). + Where(sq.Eq{"id": fileID}) + if _, err := deleteFileInfoQuery.Exec(); err != nil { + return err + } + } + deleteQuery := s.getQueryBuilder(db). Delete(s.tablePrefix + "blocks"). Where(sq.Eq{"id": blockID}) @@ -931,6 +963,44 @@ func (s *SQLStore) deleteBlockChildren(db sq.BaseRunner, boardID string, parentI return err } + fileDeleteQuery := s.getQueryBuilder(db). + Select(s.blockFields("")...). + From(s.tablePrefix + "blocks"). + Where(sq.Eq{"board_id": boardID}) + + rows, err := fileDeleteQuery.Query() + if err != nil { + return err + } + defer s.CloseRows(rows) + blocks, err := s.blocksFromRows(rows) + if err != nil { + return err + } + + fileIDs := make([]string, 0, len(blocks)) + for _, block := range blocks { + fileIDWithExtention, fileIDExists := block.Fields["fileId"] + if fileIDExists { + fileIDs = append(fileIDs, retrieveFileIDFromBlockFieldStorage(fileIDWithExtention.(string))) + } + attachmentIDWithExtention, attachmentIDExists := block.Fields["attachmentId"] + if attachmentIDExists { + fileIDs = append(fileIDs, retrieveFileIDFromBlockFieldStorage(attachmentIDWithExtention.(string))) + } + } + + if len(fileIDs) > 0 { + deleteFileInfoQuery := s.getQueryBuilder(db). + Update("FileInfo"). + Set("DeleteAt", model.GetMillis()). + Where(sq.Eq{"id": fileIDs}) + + if _, err := deleteFileInfoQuery.Exec(); err != nil { + return err + } + } + deleteQuery := s.getQueryBuilder(db). Delete(s.tablePrefix + "blocks"). Where(sq.Eq{"board_id": boardID}) From e4630d1a843ffbcdc57b3493a77a08d2cbe72eed Mon Sep 17 00:00:00 2001 From: Miguel de la Cruz Date: Wed, 31 May 2023 23:52:44 +0200 Subject: [PATCH 057/102] Remove product references (#4744) --- .github/workflows/ci.yml | 60 ---- .github/workflows/dev-release.yml | 68 +--- .github/workflows/lint-server.yml | 15 - .github/workflows/prod-release.yml | 68 +--- .gitignore | 1 + Makefile | 40 +-- build/MIT-COMPILED-LICENSE.md | 11 - build/gowork/main.go | 101 ------ linux/go.mod | 67 ++-- linux/go.sum | 332 ++++++------------ mattermost-plugin/Makefile | 13 +- mattermost-plugin/go.mod | 72 ++-- mattermost-plugin/go.sum | 143 ++++---- mattermost-plugin/product/api_adapter.go | 257 -------------- mattermost-plugin/product/boards_product.go | 331 ----------------- .../product/imports/boards_imports.go | 10 - server/go.mod | 4 +- server/go.sum | 113 ++---- server/services/store/storetests/boards.go | 3 + 19 files changed, 315 insertions(+), 1394 deletions(-) delete mode 100644 build/MIT-COMPILED-LICENSE.md delete mode 100644 build/gowork/main.go delete mode 100644 mattermost-plugin/product/api_adapter.go delete mode 100644 mattermost-plugin/product/boards_product.go delete mode 100644 mattermost-plugin/product/imports/boards_imports.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 93155b4a1..2b0052bf9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,21 +30,6 @@ jobs: uses: actions/checkout@v3 with: path: "focalboard" - - id: "mattermostServer" - uses: actions/checkout@v3 - continue-on-error: true - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref: ${{ env.BRANCH_NAME }} - - uses: actions/checkout@v3 - if: steps.mattermostServer.outcome == 'failure' - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Set up Go uses: actions/setup-go@v3 with: @@ -60,21 +45,6 @@ jobs: uses: actions/checkout@v3 with: path: "focalboard" - - id: "mattermostServer" - uses: actions/checkout@v3 - continue-on-error: true - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref: ${{ env.BRANCH_NAME }} - - uses: actions/checkout@v3 - if: steps.mattermostServer.outcome == 'failure' - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: npm ci run: | cd focalboard/webapp && npm ci && cd - @@ -118,21 +88,6 @@ jobs: uses: actions/checkout@v3 with: path: "focalboard" - - id: "mattermostServer" - uses: actions/checkout@v3 - continue-on-error: true - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref: ${{ env.BRANCH_NAME }} - - uses: actions/checkout@v3 - if: steps.mattermostServer.outcome == 'failure' - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Set up Go uses: actions/setup-go@v3 @@ -155,21 +110,6 @@ jobs: uses: actions/checkout@v3 with: path: "focalboard" - - id: "mattermostServer" - uses: actions/checkout@v3 - continue-on-error: true - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref: ${{ env.BRANCH_NAME }} - - uses: actions/checkout@v3 - if: steps.mattermostServer.outcome == 'failure' - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Set up Go uses: actions/setup-go@v3 diff --git a/.github/workflows/dev-release.yml b/.github/workflows/dev-release.yml index da022b71f..17dcba2d3 100644 --- a/.github/workflows/dev-release.yml +++ b/.github/workflows/dev-release.yml @@ -19,21 +19,6 @@ jobs: - uses: actions/checkout@v3 with: path: "focalboard" - - id: "mattermostServer" - uses: actions/checkout@v3 - continue-on-error: true - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref: ${{ env.BRANCH_NAME }} - - uses: actions/checkout@v3 - if: steps.mattermostServer.outcome == 'failure' - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go @@ -63,11 +48,11 @@ jobs: - name: apt-get update run: sudo apt-get update - - name: apt-get install libgtk-3-dev - run: sudo apt-get install libgtk-3-dev + - name: apt-get install -y libgtk-3-dev + run: sudo apt-get install -y libgtk-3-dev - - name: apt-get install libwebkit2gtk-4.0-dev - run: sudo apt-get install libwebkit2gtk-4.0-dev + - name: apt-get install -y libwebkit2gtk-4.0-dev + run: sudo apt-get install -y libwebkit2gtk-4.0-dev - name: Build Linux server and app run: cd focalboard/; make server-linux-package linux-app @@ -95,21 +80,6 @@ jobs: uses: actions/checkout@v3 with: path: "focalboard" - - id: "mattermostServer" - uses: actions/checkout@v3 - continue-on-error: true - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref: ${{ env.BRANCH_NAME }} - - uses: actions/checkout@v3 - if: steps.mattermostServer.outcome == 'failure' - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go @@ -153,21 +123,6 @@ jobs: uses: actions/checkout@v3 with: path: "focalboard" - - id: "mattermostServer" - uses: actions/checkout@v3 - continue-on-error: true - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref: ${{ env.BRANCH_NAME }} - - uses: actions/checkout@v3 - if: steps.mattermostServer.outcome == 'failure' - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go @@ -223,21 +178,6 @@ jobs: - uses: actions/checkout@v3 with: path: "focalboard" - - id: "mattermostServer" - uses: actions/checkout@v3 - continue-on-error: true - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref: ${{ env.BRANCH_NAME }} - - uses: actions/checkout@v3 - if: steps.mattermostServer.outcome == 'failure' - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go diff --git a/.github/workflows/lint-server.yml b/.github/workflows/lint-server.yml index 3e505f1cd..88bf97b6c 100644 --- a/.github/workflows/lint-server.yml +++ b/.github/workflows/lint-server.yml @@ -34,21 +34,6 @@ jobs: - uses: actions/checkout@v3 with: path: "focalboard" - - id: "mattermostServer" - uses: actions/checkout@v3 - continue-on-error: true - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref: ${{ env.BRANCH_NAME }} - - uses: actions/checkout@v3 - if: steps.mattermostServer.outcome == 'failure' - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: set up golangci-lint run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.50.1 - name: lint diff --git a/.github/workflows/prod-release.yml b/.github/workflows/prod-release.yml index 781843a68..05df6126c 100644 --- a/.github/workflows/prod-release.yml +++ b/.github/workflows/prod-release.yml @@ -16,21 +16,6 @@ jobs: uses: actions/checkout@v3 with: path: "focalboard" - - id: "mattermostServer" - uses: actions/checkout@v3 - continue-on-error: true - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref: ${{ env.BRANCH_NAME }} - - uses: actions/checkout@v3 - if: steps.mattermostServer.outcome == 'failure' - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go @@ -60,11 +45,11 @@ jobs: - name: apt-get update run: sudo apt-get update - - name: apt-get install libgtk-3-dev - run: sudo apt-get install libgtk-3-dev + - name: apt-get install -y libgtk-3-dev + run: sudo apt-get install -y libgtk-3-dev - - name: apt-get install libwebkit2gtk-4.0-dev - run: sudo apt-get install libwebkit2gtk-4.0-dev + - name: apt-get install -y libwebkit2gtk-4.0-dev + run: sudo apt-get install -y libwebkit2gtk-4.0-dev - name: Build Linux server and app run: cd focalboard; make server-linux-package linux-app @@ -92,21 +77,6 @@ jobs: uses: actions/checkout@v3 with: path: "focalboard" - - id: "mattermostServer" - uses: actions/checkout@v3 - continue-on-error: true - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref: ${{ env.BRANCH_NAME }} - - uses: actions/checkout@v3 - if: steps.mattermostServer.outcome == 'failure' - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go @@ -151,21 +121,6 @@ jobs: uses: actions/checkout@v3 with: path: "focalboard" - - id: "mattermostServer" - uses: actions/checkout@v3 - continue-on-error: true - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref: ${{ env.BRANCH_NAME }} - - uses: actions/checkout@v3 - if: steps.mattermostServer.outcome == 'failure' - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go @@ -223,21 +178,6 @@ jobs: uses: actions/checkout@v3 with: path: "focalboard" - - id: "mattermostServer" - uses: actions/checkout@v3 - continue-on-error: true - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref: ${{ env.BRANCH_NAME }} - - uses: actions/checkout@v3 - if: steps.mattermostServer.outcome == 'failure' - with: - repository: "mattermost/mattermost-server" - fetch-depth: "20" - path: "mattermost-server" - ref : "b61c096497ac1f22f64b77afe58d0dd5a72b38f1" - name: Replace token 1 server run: sed -i -e "s,placeholder_rudder_dataplane_url,${{ secrets.RUDDER_DATAPLANE_URL }},g" ${{ github.workspace }}/focalboard/server/services/telemetry/telemetry.go diff --git a/.gitignore b/.gitignore index 1d8fbe633..3b2e32706 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,7 @@ build/Release node_modules dist pack +package bin debug __debug_bin diff --git a/Makefile b/Makefile index 9d74bef1f..f10c56392 100644 --- a/Makefile +++ b/Makefile @@ -39,18 +39,14 @@ prebuild: ## Run prebuild actions (install dependencies etc.). ci: webapp-ci server-test ## Simulate CI, locally. -setup-go-work: export EXCLUDE_ENTERPRISE ?= true -setup-go-work: ## Sets up a go.work file - go run ./build/gowork/main.go - -templates-archive: setup-go-work ## Build templates archive file +templates-archive: ## Build templates archive file cd server/assets/build-template-archive; go run -tags '$(BUILD_TAGS)' main.go --dir="../templates-boardarchive" --out="../templates.boardarchive" -server: setup-go-work ## Build server for local environment. +server: ## Build server for local environment. $(eval LDFLAGS += -X "github.com/mattermost/focalboard/server/model.Edition=dev") cd server; go build -ldflags '$(LDFLAGS)' -tags '$(BUILD_TAGS)' -o ../bin/focalboard-server ./main -server-mac: setup-go-work ## Build server for Mac. +server-mac: ## Build server for Mac. mkdir -p bin/mac $(eval LDFLAGS += -X "github.com/mattermost/focalboard/server/model.Edition=mac") ifeq ($(FB_PROD),) @@ -60,21 +56,21 @@ else cd server; env GOOS=darwin GOARCH=amd64 CGO_ENABLED=1 go build -ldflags '$(LDFLAGS)' -tags '$(BUILD_TAGS)' -o ../bin/mac/focalboard-server ./main endif -server-linux: setup-go-work ## Build server for Linux. +server-linux: ## Build server for Linux. mkdir -p bin/linux $(eval LDFLAGS += -X "github.com/mattermost/focalboard/server/model.Edition=linux") cd server; env GOOS=linux GOARCH=$(arch) go build -ldflags '$(LDFLAGS)' -tags '$(BUILD_TAGS)' -o ../bin/linux/focalboard-server ./main -server-docker: setup-go-work ## Build server for Docker Architectures. +server-docker: ## Build server for Docker Architectures. mkdir -p bin/docker $(eval LDFLAGS += -X "github.com/mattermost/focalboard/server/model.Edition=linux") cd server; env GOOS=$(os) GOARCH=$(arch) go build -ldflags '$(LDFLAGS)' -tags '$(BUILD_TAGS)' -o ../bin/docker/focalboard-server ./main -server-win: setup-go-work ## Build server for Windows. +server-win: ## Build server for Windows. $(eval LDFLAGS += -X "github.com/mattermost/focalboard/server/model.Edition=win") cd server; env GOOS=windows GOARCH=amd64 go build -ldflags '$(LDFLAGS)' -tags '$(BUILD_TAGS)' -o ../bin/win/focalboard-server.exe ./main -server-dll: setup-go-work ## Build server as Windows DLL. +server-dll: ## Build server as Windows DLL. $(eval LDFLAGS += -X "github.com/mattermost/focalboard/server/model.Edition=win") cd server; env GOOS=windows GOARCH=amd64 go build -ldflags '$(LDFLAGS)' -tags '$(BUILD_TAGS)' -buildmode=c-shared -o ../bin/win-dll/focalboard-server.dll ./main @@ -84,7 +80,6 @@ server-linux-package: server-linux webapp cp bin/linux/focalboard-server package/${PACKAGE_FOLDER}/bin cp -R webapp/pack package/${PACKAGE_FOLDER}/pack cp server-config.json package/${PACKAGE_FOLDER}/config.json - cp build/MIT-COMPILED-LICENSE.md package/${PACKAGE_FOLDER} cp NOTICE.txt package/${PACKAGE_FOLDER} cp webapp/NOTICE.txt package/${PACKAGE_FOLDER}/webapp-NOTICE.txt mkdir -p dist @@ -97,7 +92,6 @@ server-linux-package-docker: cp bin/linux/focalboard-server package/${PACKAGE_FOLDER}/bin cp -R webapp/pack package/${PACKAGE_FOLDER}/pack cp server-config.json package/${PACKAGE_FOLDER}/config.json - cp build/MIT-COMPILED-LICENSE.md package/${PACKAGE_FOLDER} cp NOTICE.txt package/${PACKAGE_FOLDER} cp webapp/NOTICE.txt package/${PACKAGE_FOLDER}/webapp-NOTICE.txt mkdir -p dist @@ -108,7 +102,7 @@ generate: ## Install and run code generators. cd server; go install github.com/golang/mock/mockgen@v1.6.0 cd server; go generate ./... -server-lint: setup-go-work ## Run linters on server code. +server-lint: ## Run linters on server code. @if ! [ -x "$$(command -v golangci-lint)" ]; then \ echo "golangci-lint is not installed. Please see https://github.com/golangci/golangci-lint#install-golangci-lint for installation instructions."; \ exit 1; \ @@ -135,20 +129,20 @@ server-test: server-test-sqlite server-test-mysql server-test-mariadb server-tes server-test-sqlite: export FOCALBOARD_UNIT_TESTING=1 -server-test-sqlite: setup-go-work ## Run server tests using sqlite +server-test-sqlite: ## Run server tests using sqlite cd server; go test -tags '$(BUILD_TAGS)' -race -v -coverpkg=./... -coverprofile=server-sqlite-profile.coverage -count=1 -timeout=30m ./... cd server; go tool cover -func server-sqlite-profile.coverage server-test-mini-sqlite: export FOCALBOARD_UNIT_TESTING=1 -server-test-mini-sqlite: setup-go-work ## Run server tests using sqlite +server-test-mini-sqlite: ## Run server tests using sqlite cd server/integrationtests; go test -tags '$(BUILD_TAGS)' $(RACE) -v -count=1 -timeout=30m ./... server-test-mysql: export FOCALBOARD_UNIT_TESTING=1 server-test-mysql: export FOCALBOARD_STORE_TEST_DB_TYPE=mysql server-test-mysql: export FOCALBOARD_STORE_TEST_DOCKER_PORT=44446 -server-test-mysql: setup-go-work ## Run server tests using mysql +server-test-mysql: ## Run server tests using mysql @echo Starting docker container for mysql docker-compose -f ./docker-testing/docker-compose-mysql.yml down -v --remove-orphans docker-compose -f ./docker-testing/docker-compose-mysql.yml run start_dependencies @@ -176,7 +170,7 @@ server-test-postgres: export FOCALBOARD_UNIT_TESTING=1 server-test-postgres: export FOCALBOARD_STORE_TEST_DB_TYPE=postgres server-test-postgres: export FOCALBOARD_STORE_TEST_DOCKER_PORT=44447 -server-test-postgres: setup-go-work ## Run server tests using postgres +server-test-postgres: ## Run server tests using postgres @echo Starting docker container for postgres docker-compose -f ./docker-testing/docker-compose-postgres.yml down -v --remove-orphans docker-compose -f ./docker-testing/docker-compose-postgres.yml run start_dependencies @@ -205,14 +199,6 @@ watch-plugin: modd-precheck ## Run and upload the plugin to a development server live-watch-plugin: modd-precheck ## Run and update locally the plugin in the development server cd mattermost-plugin; make live-watch -.PHONY: build-product -build-product: ## Builds the product as something the Mattermost server will pull files from when packaging a release - cd mattermost-plugin; make build-product - -.PHONY: watch-product -watch-product: ## Run the product as something the Mattermost web app will watch for - cd mattermost-plugin; make watch-product - mac-app: server-mac webapp ## Build Mac application. rm -rf mac/temp rm -rf mac/dist @@ -228,7 +214,6 @@ mac-app: server-mac webapp ## Build Mac application. mkdir -p mac/dist cp -R mac/temp/focalboard.xcarchive/Products/Applications/Focalboard.app mac/dist/ # xcodebuild -exportArchive -archivePath mac/temp/focalboard.xcarchive -exportPath mac/dist -exportOptionsPlist mac/export.plist - cp build/MIT-COMPILED-LICENSE.md mac/dist cp NOTICE.txt mac/dist cp webapp/NOTICE.txt mac/dist/webapp-NOTICE.txt cd mac/dist; zip -r focalboard-mac.zip Focalboard.app MIT-COMPILED-LICENSE.md NOTICE.txt webapp-NOTICE.txt @@ -244,7 +229,6 @@ linux-app: webapp ## Build Linux application. mkdir -p linux/dist mkdir -p linux/temp/focalboard-app cp app-config.json linux/temp/focalboard-app/config.json - cp build/MIT-COMPILED-LICENSE.md linux/temp/focalboard-app/ cp NOTICE.txt linux/temp/focalboard-app/ cp webapp/NOTICE.txt linux/temp/focalboard-app/webapp-NOTICE.txt cp -R webapp/pack linux/temp/focalboard-app/pack diff --git a/build/MIT-COMPILED-LICENSE.md b/build/MIT-COMPILED-LICENSE.md deleted file mode 100644 index dc79e0d76..000000000 --- a/build/MIT-COMPILED-LICENSE.md +++ /dev/null @@ -1,11 +0,0 @@ -Mattermost MIT Compiled License - -**Note: This license does not cover source code; for information on source code licensing see LICENSE.txt in the source code from which this project was compiled.** - -Copyright (c) 2016-present Mattermost, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software; - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/build/gowork/main.go b/build/gowork/main.go deleted file mode 100644 index b8619ebdf..000000000 --- a/build/gowork/main.go +++ /dev/null @@ -1,101 +0,0 @@ -package main - -import ( - "fmt" - "os" - "strings" -) - -const ( - filename = "go.work" -) - -func main() { - force := false - if len(os.Args) == 2 && strings.ToLower(os.Args[1]) == "-f" { - force = true - } - - if _, err := os.Stat(filename); err == nil && !force { - // go.work already exists and force flag not specified - fmt.Fprintln(os.Stdout, "go.work already exists and -f (force) not specified; nothing to do.") - os.Exit(0) - } - - f, err := os.Create(filename) - if err != nil { - fmt.Fprintf(os.Stderr, "error creating %s: %s", filename, err.Error()) - os.Exit(-1) - } - defer f.Close() - - isCI := isCI() - content := makeGoWork(isCI) - - _, err = f.WriteString(content) - if err != nil { - fmt.Fprintf(os.Stderr, "error writing %s: %s", filename, err.Error()) - os.Exit(-1) - } - - fmt.Fprintln(os.Stdout, "go.work written successfully.") - fmt.Fprintln(os.Stdout, content) -} - -func makeGoWork(ci bool) string { - repos := map[string]string{ - "../mattermost-server": "EXCLUDE_SERVER", - "../enterprise": "EXCLUDE_ENTERPRISE", - "./mattermost-plugin": "EXCLUDE_PLUGIN", - } - - var b strings.Builder - - b.WriteString("go 1.19\n\n") - b.WriteString("use ./server\n") - - for repo, envVarName := range repos { - if !isEnvVarTrue(envVarName, true) { - b.WriteString(fmt.Sprintf("use %s\n", repo)) - } - } - - if ci { - b.WriteString("use ./linux\n") - } - return b.String() -} - -func isCI() bool { - vars := map[string]bool{ - // var name: must_be_true (false means being defined is enough) - "CIRCLECI": true, - "GITHUB_ACTIONS": true, - "GITLAB_CI": false, - "TRAVIS": true, - } - - for name, mustBeTrue := range vars { - if isEnvVarTrue(name, mustBeTrue) { - return true - } - } - return false -} - -func isEnvVarTrue(name string, mustBeTrue bool) bool { - val, ok := os.LookupEnv(name) - if !ok { - return false - } - - if !mustBeTrue { - return true - } - - switch strings.ToLower(val) { - case "t", "1", "true", "y", "yes": - return true - } - return false -} diff --git a/linux/go.mod b/linux/go.mod index 497722568..43d5ea479 100644 --- a/linux/go.mod +++ b/linux/go.mod @@ -6,8 +6,8 @@ replace github.com/mattermost/focalboard/server => ../server require ( github.com/google/uuid v1.3.0 - github.com/mattermost/focalboard/server v0.0.0-00010101000000-000000000000 - github.com/mattermost/mattermost-server/v6 v6.0.0-20221214122404-8d90c7042f93 + github.com/mattermost/focalboard/server v0.0.0-20230104182634-f909c2552e37 + github.com/mattermost/mattermost-server/v6 v6.0.0-20230321114510-b61c096497ac github.com/webview/webview v0.0.0-20220314230258-a2b7746141c3 ) @@ -16,7 +16,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver v3.5.1+incompatible // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a // indirect @@ -24,21 +24,21 @@ require ( github.com/francoispqt/gojay v1.2.13 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect - github.com/go-sql-driver/mysql v1.6.0 // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/golang-migrate/migrate/v4 v4.15.2 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/graph-gophers/graphql-go v1.4.0 // indirect - github.com/hashicorp/go-hclog v1.3.1 // indirect - github.com/hashicorp/go-plugin v1.4.6 // indirect + github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a // indirect + github.com/hashicorp/go-hclog v1.4.0 // indirect + github.com/hashicorp/go-plugin v1.4.8 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/jmoiron/sqlx v1.3.5 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/klauspost/compress v1.15.12 // indirect - github.com/klauspost/cpuid/v2 v2.2.1 // indirect + github.com/klauspost/compress v1.15.14 // indirect + github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/krolaw/zipstream v0.0.0-20180621105154-0a2661891f94 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect @@ -46,18 +46,17 @@ require ( github.com/magiconair/properties v1.8.6 // indirect github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 // indirect github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d // indirect - github.com/mattermost/logr/v2 v2.0.15 // indirect - github.com/mattermost/mattermost-plugin-api v0.0.29-0.20220801143717-73008cfda2fb // indirect + github.com/mattermost/logr/v2 v2.0.16 // indirect + github.com/mattermost/mattermost-plugin-api v0.1.1 // indirect github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e // indirect github.com/mattermost/squirrel v0.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/minio/md5-simd v1.1.2 // indirect - github.com/minio/minio-go/v7 v7.0.43 // indirect + github.com/minio/minio-go/v7 v7.0.45 // indirect github.com/minio/sha256-simd v1.0.0 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -65,14 +64,14 @@ require ( github.com/oklog/run v1.1.0 // indirect github.com/pborman/uuid v1.2.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/philhofer/fwd v1.1.1 // indirect + github.com/philhofer/fwd v1.1.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.33.0 // indirect github.com/prometheus/procfs v0.7.3 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa // indirect github.com/rivo/uniseg v0.4.3 // indirect github.com/rs/xid v1.4.0 // indirect github.com/rudderlabs/analytics-go v3.3.3+incompatible // indirect @@ -86,38 +85,38 @@ require ( github.com/stretchr/objx v0.5.0 // indirect github.com/stretchr/testify v1.8.1 // indirect github.com/subosito/gotenv v1.2.0 // indirect - github.com/tidwall/gjson v1.14.3 // indirect + github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect - github.com/tinylib/msgp v1.1.6 // indirect + github.com/tinylib/msgp v1.1.8 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/wiggin77/merror v1.0.4 // indirect github.com/wiggin77/srslog v1.0.1 // indirect github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect github.com/yuin/goldmark v1.5.3 // indirect - golang.org/x/crypto v0.2.0 // indirect + golang.org/x/crypto v0.5.0 // indirect golang.org/x/mod v0.7.0 // indirect - golang.org/x/net v0.2.0 // indirect + golang.org/x/net v0.5.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.2.0 // indirect - golang.org/x/text v0.4.0 // indirect - golang.org/x/tools v0.3.0 // indirect - google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1 // indirect - google.golang.org/grpc v1.50.1 // indirect + golang.org/x/sys v0.4.0 // indirect + golang.org/x/text v0.6.0 // indirect + golang.org/x/tools v0.5.0 // indirect + google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf // indirect + google.golang.org/grpc v1.51.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/uint128 v1.2.0 // indirect - modernc.org/cc/v3 v3.36.0 // indirect - modernc.org/ccgo/v3 v3.16.6 // indirect - modernc.org/libc v1.16.7 // indirect - modernc.org/mathutil v1.4.1 // indirect - modernc.org/memory v1.1.1 // indirect - modernc.org/opt v0.1.1 // indirect - modernc.org/sqlite v1.18.0 // indirect - modernc.org/strutil v1.1.1 // indirect - modernc.org/token v1.0.0 // indirect + modernc.org/cc/v3 v3.40.0 // indirect + modernc.org/ccgo/v3 v3.16.13 // indirect + modernc.org/libc v1.22.2 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.5.0 // indirect + modernc.org/opt v0.1.3 // indirect + modernc.org/sqlite v1.20.1 // indirect + modernc.org/strutil v1.1.3 // indirect + modernc.org/token v1.1.0 // indirect ) diff --git a/linux/go.sum b/linux/go.sum index 58bd47832..68ebfbdb7 100644 --- a/linux/go.sum +++ b/linux/go.sum @@ -199,8 +199,9 @@ github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6 github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= @@ -404,7 +405,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -425,8 +425,7 @@ github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiD github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= @@ -483,8 +482,9 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= @@ -592,8 +592,8 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE= @@ -621,6 +621,7 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -651,8 +652,8 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/graph-gophers/graphql-go v1.4.0 h1:JE9wveRTSXwJyjdRd6bOQ7Ob5bewTUQ58Jv4OiVdpdE= -github.com/graph-gophers/graphql-go v1.4.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= +github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a h1:i0+Se9S+2zL5CBxJouqn2Ej6UQMwH1c57ZB6DVnqck4= +github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -670,18 +671,16 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw= -github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-hclog v1.3.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.4.0 h1:ctuWFGrhFha8BnnzxqeRGidlEcQkDyL5u8J8t5eA11I= +github.com/hashicorp/go-hclog v1.4.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.4.4 h1:NVdrSdFRt3SkZtNckJ6tog7gbpRrcbOjQi/rgF7JYWQ= -github.com/hashicorp/go-plugin v1.4.4/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= -github.com/hashicorp/go-plugin v1.4.6/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= +github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM= +github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= @@ -696,8 +695,7 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I= -github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -804,14 +802,12 @@ github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdY github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY= -github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.15.14 h1:i7WCKDToww0wA+9qrUZ1xOjp218vfFo3nTU6UHp+gOc= +github.com/klauspost/compress v1.15.14/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.13 h1:1XxvOiqXZ8SULZUKim/wncr3wZ38H4yCuVDvKdK9OGs= -github.com/klauspost/cpuid/v2 v2.0.13/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= -github.com/klauspost/cpuid/v2 v2.2.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= +github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -841,8 +837,7 @@ github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= -github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= @@ -865,18 +860,13 @@ github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 h1:Khvh6waxG github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404/go.mod h1:RyS7FDNQlzF1PsjbJWHRI35exqaKGSO9qD4iv8QjE34= github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d h1:/RJ/UV7M5c7L2TQ0KNm4yZxxFvC1nvRz/gY/Daa35aI= github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d/go.mod h1:HLbgMEI5K131jpxGazJ97AxfPDt31osq36YS1oxFQPQ= -github.com/mattermost/logr/v2 v2.0.15 h1:+WNbGcsc3dBao65eXlceB6dTILNJRIrvubnsTl3zBew= -github.com/mattermost/logr/v2 v2.0.15/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg= -github.com/mattermost/mattermost-plugin-api v0.0.29-0.20220801143717-73008cfda2fb h1:q1qXKVv59rA2gcQ7lVLc5OlWBmfsR3i8mdGD5EZesyk= -github.com/mattermost/mattermost-plugin-api v0.0.29-0.20220801143717-73008cfda2fb/go.mod h1:PIeo40t9VTA4Wu1FwjzH7QmcgC3SRyk/ohCwJw4/oSo= -github.com/mattermost/mattermost-server/v6 v6.0.0-20220802151854-f07c31c5d933 h1:h7EibO8cwWeK8dLhC/A5tKGbkYSuJKZ0+2EXW7jDHoA= -github.com/mattermost/mattermost-server/v6 v6.0.0-20220802151854-f07c31c5d933/go.mod h1:otnBnKY9Y0eNkUKeD161de+BUBlESwANTnrkPT/392Y= -github.com/mattermost/mattermost-server/v6 v6.0.0-20221130200243-06e964b86b0d h1:CKJXDUCkRrfy1U9sZHOpvACOtkthV5iWt2boHUK720I= -github.com/mattermost/mattermost-server/v6 v6.0.0-20221130200243-06e964b86b0d/go.mod h1:U3gSM0I15WSMHPpDEU30mmc4JrbSDk+8F1+MFLOHWD0= -github.com/mattermost/mattermost-server/v6 v6.0.0-20221214122404-8d90c7042f93 h1:mGN2D6KhjKosQdZ+BHzmWxsA/tRK9FiR+nUd38nSZQY= -github.com/mattermost/mattermost-server/v6 v6.0.0-20221214122404-8d90c7042f93/go.mod h1:U3gSM0I15WSMHPpDEU30mmc4JrbSDk+8F1+MFLOHWD0= -github.com/mattermost/morph v0.0.0-20220401091636-39f834798da8 h1:gwliVjCTqAC01mSCNqa5nJ/4MmGq50vrjsottIhQ4d8= -github.com/mattermost/morph v0.0.0-20220401091636-39f834798da8/go.mod h1:jxM3g1bx+k2Thz7jofcHguBS8TZn5Pc+o5MGmORObhw= +github.com/mattermost/logr/v2 v2.0.16 h1:jnePX4cPskC3WDFvUardh/xZfxNdsFXbEERJQ1kUEDE= +github.com/mattermost/logr/v2 v2.0.16/go.mod h1:1dm/YhTpozsqANXxo5Pi5zYLBsal2xY0pX+JZNbzYJY= +github.com/mattermost/mattermost-plugin-api v0.1.1 h1:bNnPbWCLWZpT/k2kjUxNnzCfUggU8WKs2ddz7hNjg1U= +github.com/mattermost/mattermost-plugin-api v0.1.1/go.mod h1:9yZhtg0bBj3kqSTjXnjYBMZoTsWbe3ajdFMdl9/Jz34= +github.com/mattermost/mattermost-server/v6 v6.0.0-20230321114510-b61c096497ac h1:AiV4kplzWpzuHvoh9Mfsy5FHOLRZA0cSIuFMg/32qqg= +github.com/mattermost/mattermost-server/v6 v6.0.0-20230321114510-b61c096497ac/go.mod h1:o61MGMh7We01wGr1ydGDA5mmNpjTzaBVWUAlezsgx50= +github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e h1:VfNz+fvJ3DxOlALM22Eea8ONp5jHrybKBCcCtDPVlss= github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e/go.mod h1:xo0ljDknTpPxEdhhrUdwhLCexIsYyDKS6b41HqG8wGU= github.com/mattermost/squirrel v0.2.0 h1:8ZWeyf+MWQ2cL7hu9REZgLtz2IJi51qqZEovI3T3TT8= github.com/mattermost/squirrel v0.2.0/go.mod h1:NPPtk+CdpWre4GxMGoOpzEVFVc0ZoEFyJBZGCtn9nSU= @@ -886,8 +876,8 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -897,16 +887,16 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= @@ -920,15 +910,13 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.28 h1:VMr3K5qGIEt+/KW3poopRh8mzi5RwuCjmrmstK196Fg= -github.com/minio/minio-go/v7 v7.0.28/go.mod h1:x81+AX5gHSfCSqw7jxRKHvxUXMlE5uKX0Vb75Xk5yYg= -github.com/minio/minio-go/v7 v7.0.43/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw= +github.com/minio/minio-go/v7 v7.0.45 h1:g4IeM9M9pW/Lo8AGGNOjBZYlvmtlE1N5TQEYWXRWzIs= +github.com/minio/minio-go/v7 v7.0.45/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= @@ -1041,8 +1029,8 @@ github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= -github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= +github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -1104,10 +1092,10 @@ github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa h1:tEkEyxYeZ43TR55QU/hsIt9aRGBxbgGuz9CGykjvogY= +github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -1120,8 +1108,7 @@ github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rudderlabs/analytics-go v3.3.2+incompatible h1:bDajEJTYhfHjNYxbQFMA/2dHlOjyeSgxS7GPIdMZ52Q= -github.com/rudderlabs/analytics-go v3.3.2+incompatible/go.mod h1:LF8/ty9kUX4PTY3l5c97K3nZZaX5Hwsvt+NBaRL/f30= +github.com/rudderlabs/analytics-go v3.3.3+incompatible h1:OG0XlKoXfr539e2t1dXtTB+Gr89uFW+OUNQBVhHIIBY= github.com/rudderlabs/analytics-go v3.3.3+incompatible/go.mod h1:LF8/ty9kUX4PTY3l5c97K3nZZaX5Hwsvt+NBaRL/f30= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -1135,8 +1122,7 @@ github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/segmentio/backo-go v0.0.0-20200129164019-23eae7c10bd3 h1:ZuhckGJ10ulaKkdvJtiAqsLTiPrLaXSdnVgXJKJkTxE= -github.com/segmentio/backo-go v0.0.0-20200129164019-23eae7c10bd3/go.mod h1:9/Rh6yILuLysoQnZ2oNooD2g7aBnvM7r/fNVxRNWfBc= +github.com/segmentio/backo-go v1.0.1 h1:68RQccglxZeyURy93ASB/2kc9QudzgIDexJ927N++y4= github.com/segmentio/backo-go v1.0.1/go.mod h1:9/Rh6yILuLysoQnZ2oNooD2g7aBnvM7r/fNVxRNWfBc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= @@ -1173,8 +1159,8 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -1217,8 +1203,8 @@ github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -1229,8 +1215,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -1239,17 +1225,16 @@ github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= -github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo= -github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw= -github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= +github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= +github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -1275,9 +1260,7 @@ github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAh github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/webview/webview v0.0.0-20220314230258-a2b7746141c3 h1:8joKgFslmiNmyA0Cvw/xgkdKZOYiXKsHlnG5OWmJEHA= github.com/webview/webview v0.0.0-20220314230258-a2b7746141c3/go.mod h1:rpXAuuHgyEJb6kXcXldlkOjU6y4x+YcASKKXJNUhh0Y= -github.com/wiggin77/merror v1.0.2/go.mod h1:uQTcIU0Z6jRK4OwqganPYerzQxSFJ4GSHM3aurxxQpg= -github.com/wiggin77/merror v1.0.3 h1:8+ZHV+aSnJoYghE3EUThl15C6rvF2TYRSvOSBjdmNR8= -github.com/wiggin77/merror v1.0.3/go.mod h1:H2ETSu7/bPE0Ymf4bEwdUoo73OOEkdClnoRisfw0Nm0= +github.com/wiggin77/merror v1.0.4 h1:XxFLEevmQQfgJW2AxhapuMG7C1fQqfbim/XyUmYv/ZM= github.com/wiggin77/merror v1.0.4/go.mod h1:H2ETSu7/bPE0Ymf4bEwdUoo73OOEkdClnoRisfw0Nm0= github.com/wiggin77/srslog v1.0.1 h1:gA2XjSMy3DrRdX9UqLuDtuVAAshb8bE1NhX1YK0Qe+8= github.com/wiggin77/srslog v1.0.1/go.mod h1:fehkyYDq1QfuYn60TDPu9YdY2bB85VUW2mvN1WynEls= @@ -1300,8 +1283,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.12 h1:6hffw6vALvEDqJ19dOJvJKOoAOKe4NDaTqvd2sktGN0= -github.com/yuin/goldmark v1.4.12/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.5.3 h1:3HUJmBFbQW9fhQOzMgseU134xfi6hU+mjWywx5Ty+/M= github.com/yuin/goldmark v1.5.3/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= @@ -1357,7 +1340,7 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -1397,9 +1380,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= +golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1448,8 +1430,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1522,9 +1504,10 @@ golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220614195744-fb05da6f9022 h1:0qjDla5xICC2suMtyRH/QqX3B1btXTfNsIt/i4LFgO0= -golang.org/x/net v0.0.0-20220614195744-fb05da6f9022/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1559,8 +1542,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1675,7 +1658,6 @@ golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210818153620-00dd8d7831e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1689,20 +1671,22 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 h1:PgOr27OhUx2IRqGJ2RxAWI4dJQ7bi9cSrB82uzFzfUA= -golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1711,9 +1695,10 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1790,7 +1775,6 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1805,16 +1789,16 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY= -golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4= +golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= @@ -1943,9 +1927,8 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220614165028-45ed7f3ff16e h1:ubR4JUtqN3ffdFjpKylv8scWk/mZstGmzXbgYSkuMl0= -google.golang.org/genproto v0.0.0-20220614165028-45ed7f3ff16e/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf h1:/JqRexUvugu6JURQ0O7RfV1EnvgrOxUV4tSjuAv0Sr0= +google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= @@ -1982,9 +1965,8 @@ google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1999,8 +1981,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -2018,8 +1999,7 @@ gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKW gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI= -gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= @@ -2108,79 +2088,16 @@ lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg= modernc.org/cc/v3 v3.32.4/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878= -modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.20/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.22/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.24 h1:vlCqjhVwX15t1uwlMPpOpNRC7JTjMZ9lT9DYHKQTFuA= -modernc.org/cc/v3 v3.35.24/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= modernc.org/ccgo/v3 v3.9.2/go.mod h1:gnJpy6NIVqkETT+L5zPsQFj7L2kkhfPMzOghRNv/CFo= -modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60= -modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw= -modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI= -modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag= -modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw= -modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ= -modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c= -modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo= -modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg= -modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I= -modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs= -modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8= -modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE= -modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk= -modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w= -modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE= -modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8= -modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc= -modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU= -modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE= -modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk= -modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI= -modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE= -modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg= -modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74= -modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU= -modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU= -modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc= -modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM= -modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ= -modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84= -modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ= -modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY= -modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w= -modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU= -modernc.org/ccgo/v3 v3.12.88/go.mod h1:0MFzUHIuSIthpVZyMWiFYMwjiFnhrN5MkvBrUwON+ZM= -modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko= -modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA= -modernc.org/ccgo/v3 v3.12.95/go.mod h1:ZcLyvtocXYi8uF+9Ebm3G8EF8HNY5hGomBqthDp4eC8= -modernc.org/ccgo/v3 v3.13.1/go.mod h1:aBYVOUfIlcSnrsRVU8VRS35y2DIfpgkmVkYZ0tpIXi4= -modernc.org/ccgo/v3 v3.15.9/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0= -modernc.org/ccgo/v3 v3.15.10/go.mod h1:wQKxoFn0ynxMuCLfFD09c8XPUCc8obfchoVR9Cn0fI8= -modernc.org/ccgo/v3 v3.15.12/go.mod h1:VFePOWoCd8uDGRJpq/zfJ29D0EVzMSyID8LCMWYbX6I= -modernc.org/ccgo/v3 v3.15.14/go.mod h1:144Sz2iBCKogb9OKwsu7hQEub3EVgOlyI8wMUPGKUXQ= -modernc.org/ccgo/v3 v3.15.15/go.mod h1:z5qltXjU4PJl0pE5nhYQCvA9DhPHiWsl5GWl89+NSYE= -modernc.org/ccgo/v3 v3.15.16/go.mod h1:XbKRMeMWMdq712Tr5ECgATYMrzJ+g9zAZEj2ktzBe24= -modernc.org/ccgo/v3 v3.15.17 h1:svaDk4rfh7XQPBwkqzjKK8bta/vK4VVL3JP6ZLbcr0w= -modernc.org/ccgo/v3 v3.15.17/go.mod h1:bofnFkpRFf5gLY+mBZIyTW6FEcp26xi2lgOFk2Rlvs0= modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8= @@ -2193,98 +2110,45 @@ modernc.org/internal v1.0.0/go.mod h1:VUD/+JAkhCpvkUitlEOnhpVxCgsBI90oTzSCRcqQVS modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= modernc.org/libc v1.9.5/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= -modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= -modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q= -modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg= -modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M= -modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU= -modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE= -modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso= -modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8= -modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8= -modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I= -modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk= -modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY= -modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE= -modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg= -modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM= -modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg= -modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo= -modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8= -modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ= -modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA= -modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM= -modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg= -modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE= -modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM= -modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU= -modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw= -modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M= -modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18= -modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8= -modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw= -modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0= -modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI= -modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE= -modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY= -modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ= -modernc.org/libc v1.11.90/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c= -modernc.org/libc v1.11.98/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c= -modernc.org/libc v1.11.99/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI= -modernc.org/libc v1.11.101/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI= -modernc.org/libc v1.11.104/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ= -modernc.org/libc v1.12.0/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ= -modernc.org/libc v1.14.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= -modernc.org/libc v1.14.2/go.mod h1:MX1GBLnRLNdvmK9azU9LCxZ5lMyhrbEMK8rG3X/Fe34= -modernc.org/libc v1.14.3/go.mod h1:GPIvQVOVPizzlqyRX3l756/3ppsAgg1QgPxjr5Q4agQ= -modernc.org/libc v1.14.6/go.mod h1:2PJHINagVxO4QW/5OQdRrvMYo+bm5ClpUFfyXCYl9ak= -modernc.org/libc v1.14.7/go.mod h1:f8xfWXW8LW41qb4X5+huVQo5dcfPlq7Cbny2TDheMv0= -modernc.org/libc v1.14.8/go.mod h1:9+JCLb1MWSY23smyOpIPbd5ED+rSS/ieiDWUpdyO3mo= -modernc.org/libc v1.14.10/go.mod h1:y1MtIWhwpJFpLYm6grAThtuXJKEsY6xkdZmXbRngIdo= -modernc.org/libc v1.14.11/go.mod h1:l5/Mz/GrZwOqzwRHA3abgSCnSeJzzTl+Ify0bAwKbAw= -modernc.org/libc v1.14.12 h1:pUBZTYoISfbb4pCf4PECENpbvwDBxeKc+/dS9LyOWFM= -modernc.org/libc v1.14.12/go.mod h1:fJdoe23MHu2ruPQkFPPqCpToDi5cckzsbmkI6Ez0LqQ= modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= modernc.org/libc v1.16.7/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0= +modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug= modernc.org/lldb v1.0.0/go.mod h1:jcRvJGWfCGodDZz8BPwiKMJxGJngQ/5DrRapkQnLob8= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8= modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= -modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM= -modernc.org/memory v1.0.6/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.0.7 h1:UE3cxTRFa5tfUibAV7Jqq8P7zRY0OlJg+yWVIIaluEE= -modernc.org/memory v1.0.7/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A= +modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= +modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/ql v1.0.0/go.mod h1:xGVyrLIatPcO2C1JvI/Co8c0sr6y91HKFNy4pt9JXEY= modernc.org/sortutil v1.1.0/go.mod h1:ZyL98OQHJgH9IEfN71VsamvJgrtRX9Dj2gX+vH86L1k= modernc.org/sqlite v1.10.6/go.mod h1:Z9FEjUtZP4qFEg6/SiADg9XCER7aYy9a/j7Pg9P7CPs= -modernc.org/sqlite v1.14.3/go.mod h1:xMpicS1i2MJ4C8+Ap0vYBqTwYfpFvdnPE6brbFOtV2Y= -modernc.org/sqlite v1.15.3 h1:3C4AWicF7S5vUUFJuBi7Ws8eWlPjqyo/c4Z1UGYBbyg= -modernc.org/sqlite v1.15.3/go.mod h1:J7GAPbk8Txp0DJnT8TGwpUqJW0Z1cK2YpzjoXaZRU8k= modernc.org/sqlite v1.18.0/go.mod h1:B9fRWZacNxJBHoCJZQr1R54zhVn3fjfl0aszflrTSxY= +modernc.org/sqlite v1.20.1 h1:z6qRLw72B0VfRrJjs3l6hWkzYDx1bo0WGVrBGP4ohhM= +modernc.org/sqlite v1.20.1/go.mod h1:fODt+bFmc/j8LcoCbMSkAuKuGmhxjG45KGc25N2705M= modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= -modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs= modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo= -modernc.org/tcl v1.9.2/go.mod h1:aw7OnlIoiuJgu1gwbTZtrKnGpDqH9wyH++jZcxdqNsg= -modernc.org/tcl v1.11.2 h1:mXpsx3AZqJt83uDiFu9UYQVBjNjaWKGCF1YDSlpCL6Y= -modernc.org/tcl v1.11.2/go.mod h1:BRzgpajcGdS2qTxniOx9c/dcxjlbA7p12eJNmiriQYo= modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= -modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk= +modernc.org/tcl v1.15.0 h1:oY+JeD11qVVSgVvodMJsu7Edf8tr5E/7tuhF5cNYz34= modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= -modernc.org/z v1.2.20/go.mod h1:zU9FiF4PbHdOTUxw+IF8j7ArBMRPsHgq10uVPt6xTzo= -modernc.org/z v1.3.2 h1:4GWBVMa48UDC7KQ9tnaggN/yTlXg+CdCX9bhgHPQ9AM= -modernc.org/z v1.3.2/go.mod h1:PEU2oK2OEA1CfzDTd+8E908qEXhC9s0MfyKp5LZsd+k= modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= +modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE= modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/mattermost-plugin/Makefile b/mattermost-plugin/Makefile index 5b836d157..6fb384355 100644 --- a/mattermost-plugin/Makefile +++ b/mattermost-plugin/Makefile @@ -60,9 +60,6 @@ all: check-style test dist apply: ./build/bin/manifest apply -setup-go-work: ## Sets up a go.work file - cd ..; go run ./build/gowork/main.go - ## Runs eslint and golangci-lint .PHONY: check-style check-style: webapp/node_modules @@ -83,7 +80,7 @@ ifneq ($(HAS_SERVER),) golangci-lint run ./... endif -templates-archive: setup-go-work ## Build templates archive file +templates-archive: ## Build templates archive file cd ../server/assets/build-template-archive; go run -tags '$(BUILD_TAGS)' main.go --dir="../templates-boardarchive" --out="../templates.boardarchive" ## Builds the server, if it exists, for all supported architectures. @@ -174,14 +171,6 @@ endif deploy-from-watch: bundle ./build/bin/pluginctl deploy $(PLUGIN_ID) dist/$(BUNDLE_NAME) -.PHONY: build-product -build-product: apply - cd webapp && npm run build:product - -.PHONY: watch-product -watch-product: apply - cd webapp && npm run start:product - ## Setup dlv for attaching, identifying the plugin PID for other targets. .PHONY: setup-attach setup-attach: diff --git a/mattermost-plugin/go.mod b/mattermost-plugin/go.mod index 6d34bf537..a1076a211 100644 --- a/mattermost-plugin/go.mod +++ b/mattermost-plugin/go.mod @@ -5,19 +5,19 @@ go 1.19 require ( github.com/golang/mock v1.6.0 github.com/gorilla/mux v1.8.0 - github.com/mattermost/focalboard/server v0.0.0-20220818150333-feb49eaf197a - github.com/mattermost/mattermost-plugin-api v0.0.29-0.20220801143717-73008cfda2fb - github.com/mattermost/mattermost-server/v6 v6.0.0-20221214122404-8d90c7042f93 + github.com/mattermost/focalboard/server v0.0.0-20230104182634-f909c2552e37 + github.com/mattermost/mattermost-plugin-api v0.1.1 + github.com/mattermost/mattermost-server/v6 v6.0.0-20230321114510-b61c096497ac github.com/stretchr/testify v1.8.1 ) require ( github.com/BurntSushi/toml v1.2.0 // indirect - github.com/Masterminds/squirrel v1.5.2 // indirect + github.com/Masterminds/squirrel v1.5.3 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver v3.5.1+incompatible // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a // indirect @@ -25,22 +25,21 @@ require ( github.com/francoispqt/gojay v1.2.13 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect - github.com/go-sql-driver/mysql v1.6.0 // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/golang-migrate/migrate/v4 v4.15.2 // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.5.9 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/graph-gophers/graphql-go v1.4.0 // indirect - github.com/hashicorp/go-hclog v1.3.1 // indirect - github.com/hashicorp/go-plugin v1.4.6 // indirect + github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a // indirect + github.com/hashicorp/go-hclog v1.4.0 // indirect + github.com/hashicorp/go-plugin v1.4.8 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/jmoiron/sqlx v1.3.5 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/klauspost/compress v1.15.12 // indirect - github.com/klauspost/cpuid/v2 v2.2.1 // indirect + github.com/klauspost/compress v1.15.14 // indirect + github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/krolaw/zipstream v0.0.0-20180621105154-0a2661891f94 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect @@ -48,15 +47,15 @@ require ( github.com/magiconair/properties v1.8.6 // indirect github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 // indirect github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d // indirect - github.com/mattermost/logr/v2 v2.0.15 // indirect + github.com/mattermost/logr/v2 v2.0.16 // indirect github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e // indirect github.com/mattermost/squirrel v0.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/minio/md5-simd v1.1.2 // indirect - github.com/minio/minio-go/v7 v7.0.43 // indirect + github.com/minio/minio-go/v7 v7.0.45 // indirect github.com/minio/sha256-simd v1.0.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect @@ -65,14 +64,15 @@ require ( github.com/oklog/run v1.1.0 // indirect github.com/pborman/uuid v1.2.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/philhofer/fwd v1.1.1 // indirect + github.com/philhofer/fwd v1.1.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.33.0 // indirect github.com/prometheus/procfs v0.7.3 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa // indirect + github.com/rivo/uniseg v0.4.3 // indirect github.com/rs/xid v1.4.0 // indirect github.com/rudderlabs/analytics-go v3.3.3+incompatible // indirect github.com/segmentio/backo-go v1.0.1 // indirect @@ -85,38 +85,40 @@ require ( github.com/spf13/viper v1.10.1 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.2.0 // indirect - github.com/tidwall/gjson v1.14.3 // indirect + github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect - github.com/tinylib/msgp v1.1.6 // indirect + github.com/tinylib/msgp v1.1.8 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/wiggin77/merror v1.0.4 // indirect github.com/wiggin77/srslog v1.0.1 // indirect github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect github.com/yuin/goldmark v1.5.3 // indirect - golang.org/x/crypto v0.2.0 // indirect + golang.org/x/crypto v0.5.0 // indirect golang.org/x/mod v0.7.0 // indirect - golang.org/x/net v0.2.0 // indirect + golang.org/x/net v0.5.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.2.0 // indirect - golang.org/x/text v0.4.0 // indirect - golang.org/x/tools v0.3.0 // indirect - google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1 // indirect - google.golang.org/grpc v1.50.1 // indirect + golang.org/x/sys v0.4.0 // indirect + golang.org/x/text v0.6.0 // indirect + golang.org/x/tools v0.5.0 // indirect + google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf // indirect + google.golang.org/grpc v1.51.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/uint128 v1.2.0 // indirect - modernc.org/cc/v3 v3.36.0 // indirect - modernc.org/ccgo/v3 v3.16.6 // indirect - modernc.org/libc v1.16.7 // indirect - modernc.org/mathutil v1.4.1 // indirect - modernc.org/memory v1.1.1 // indirect - modernc.org/opt v0.1.1 // indirect - modernc.org/sqlite v1.18.0 // indirect - modernc.org/strutil v1.1.1 // indirect - modernc.org/token v1.0.0 // indirect + modernc.org/cc/v3 v3.40.0 // indirect + modernc.org/ccgo/v3 v3.16.13 // indirect + modernc.org/libc v1.22.2 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.5.0 // indirect + modernc.org/opt v0.1.3 // indirect + modernc.org/sqlite v1.20.1 // indirect + modernc.org/strutil v1.1.3 // indirect + modernc.org/token v1.1.0 // indirect ) + +replace github.com/mattermost/focalboard/server => ../server diff --git a/mattermost-plugin/go.sum b/mattermost-plugin/go.sum index b77eb00dc..47dbae4bb 100644 --- a/mattermost-plugin/go.sum +++ b/mattermost-plugin/go.sum @@ -86,8 +86,8 @@ github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0 github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ClickHouse/clickhouse-go v1.4.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= -github.com/Masterminds/squirrel v1.5.2 h1:UiOEi2ZX4RCSkpiNDQN5kro/XIBpSRk9iTqdIRPzUXE= -github.com/Masterminds/squirrel v1.5.2/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc= +github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= @@ -200,8 +200,9 @@ github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6 github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= @@ -482,8 +483,9 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= @@ -593,7 +595,6 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE= @@ -621,6 +622,7 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -651,8 +653,8 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/graph-gophers/graphql-go v1.4.0 h1:JE9wveRTSXwJyjdRd6bOQ7Ob5bewTUQ58Jv4OiVdpdE= -github.com/graph-gophers/graphql-go v1.4.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= +github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a h1:i0+Se9S+2zL5CBxJouqn2Ej6UQMwH1c57ZB6DVnqck4= +github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -670,16 +672,16 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v1.3.1 h1:vDwF1DFNZhntP4DAjuTpOw3uEgMUpXh1pB5fW9DqHpo= -github.com/hashicorp/go-hclog v1.3.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.4.0 h1:ctuWFGrhFha8BnnzxqeRGidlEcQkDyL5u8J8t5eA11I= +github.com/hashicorp/go-hclog v1.4.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.4.6 h1:MDV3UrKQBM3du3G7MApDGvOsMYy3JQJ4exhSoKBAeVA= -github.com/hashicorp/go-plugin v1.4.6/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= +github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM= +github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= @@ -801,12 +803,12 @@ github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdY github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= -github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.15.14 h1:i7WCKDToww0wA+9qrUZ1xOjp218vfFo3nTU6UHp+gOc= +github.com/klauspost/compress v1.15.14/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.1 h1:U33DW0aiEj633gHYw3LoDNfkDiYnE5Q8M/TKJn2f2jI= -github.com/klauspost/cpuid/v2 v2.2.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= +github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -855,18 +857,16 @@ github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsI github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= -github.com/mattermost/focalboard/server v0.0.0-20220818150333-feb49eaf197a h1:cfRjcP8I0OwVkB+fqWScvq42DyAtxo4NumsXK8Z0PG0= -github.com/mattermost/focalboard/server v0.0.0-20220818150333-feb49eaf197a/go.mod h1:3WMV0yUJanfts5bZ5ZlkxM5244UROuhqzxqJkt/Efz0= github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 h1:Khvh6waxG1cHc4Cz5ef9n3XVCxRWpAKUtqg9PJl5+y8= github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404/go.mod h1:RyS7FDNQlzF1PsjbJWHRI35exqaKGSO9qD4iv8QjE34= github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d h1:/RJ/UV7M5c7L2TQ0KNm4yZxxFvC1nvRz/gY/Daa35aI= github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d/go.mod h1:HLbgMEI5K131jpxGazJ97AxfPDt31osq36YS1oxFQPQ= -github.com/mattermost/logr/v2 v2.0.15 h1:+WNbGcsc3dBao65eXlceB6dTILNJRIrvubnsTl3zBew= -github.com/mattermost/logr/v2 v2.0.15/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg= -github.com/mattermost/mattermost-plugin-api v0.0.29-0.20220801143717-73008cfda2fb h1:q1qXKVv59rA2gcQ7lVLc5OlWBmfsR3i8mdGD5EZesyk= -github.com/mattermost/mattermost-plugin-api v0.0.29-0.20220801143717-73008cfda2fb/go.mod h1:PIeo40t9VTA4Wu1FwjzH7QmcgC3SRyk/ohCwJw4/oSo= -github.com/mattermost/mattermost-server/v6 v6.0.0-20221214122404-8d90c7042f93 h1:mGN2D6KhjKosQdZ+BHzmWxsA/tRK9FiR+nUd38nSZQY= -github.com/mattermost/mattermost-server/v6 v6.0.0-20221214122404-8d90c7042f93/go.mod h1:U3gSM0I15WSMHPpDEU30mmc4JrbSDk+8F1+MFLOHWD0= +github.com/mattermost/logr/v2 v2.0.16 h1:jnePX4cPskC3WDFvUardh/xZfxNdsFXbEERJQ1kUEDE= +github.com/mattermost/logr/v2 v2.0.16/go.mod h1:1dm/YhTpozsqANXxo5Pi5zYLBsal2xY0pX+JZNbzYJY= +github.com/mattermost/mattermost-plugin-api v0.1.1 h1:bNnPbWCLWZpT/k2kjUxNnzCfUggU8WKs2ddz7hNjg1U= +github.com/mattermost/mattermost-plugin-api v0.1.1/go.mod h1:9yZhtg0bBj3kqSTjXnjYBMZoTsWbe3ajdFMdl9/Jz34= +github.com/mattermost/mattermost-server/v6 v6.0.0-20230321114510-b61c096497ac h1:AiV4kplzWpzuHvoh9Mfsy5FHOLRZA0cSIuFMg/32qqg= +github.com/mattermost/mattermost-server/v6 v6.0.0-20230321114510-b61c096497ac/go.mod h1:o61MGMh7We01wGr1ydGDA5mmNpjTzaBVWUAlezsgx50= github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e h1:VfNz+fvJ3DxOlALM22Eea8ONp5jHrybKBCcCtDPVlss= github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e/go.mod h1:xo0ljDknTpPxEdhhrUdwhLCexIsYyDKS6b41HqG8wGU= github.com/mattermost/squirrel v0.2.0 h1:8ZWeyf+MWQ2cL7hu9REZgLtz2IJi51qqZEovI3T3TT8= @@ -889,8 +889,9 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= @@ -910,8 +911,8 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.43 h1:14Q4lwblqTdlAmba05oq5xL0VBLHi06zS4yLnIkz6hI= -github.com/minio/minio-go/v7 v7.0.43/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw= +github.com/minio/minio-go/v7 v7.0.45 h1:g4IeM9M9pW/Lo8AGGNOjBZYlvmtlE1N5TQEYWXRWzIs= +github.com/minio/minio-go/v7 v7.0.45/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= @@ -1029,8 +1030,8 @@ github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= -github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= +github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -1092,8 +1093,11 @@ github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa h1:tEkEyxYeZ43TR55QU/hsIt9aRGBxbgGuz9CGykjvogY= +github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= +github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1224,16 +1228,16 @@ github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= -github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw= -github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw= -github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= +github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= +github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -1257,7 +1261,6 @@ github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9 github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -github.com/wiggin77/merror v1.0.2/go.mod h1:uQTcIU0Z6jRK4OwqganPYerzQxSFJ4GSHM3aurxxQpg= github.com/wiggin77/merror v1.0.4 h1:XxFLEevmQQfgJW2AxhapuMG7C1fQqfbim/XyUmYv/ZM= github.com/wiggin77/merror v1.0.4/go.mod h1:H2ETSu7/bPE0Ymf4bEwdUoo73OOEkdClnoRisfw0Nm0= github.com/wiggin77/srslog v1.0.1 h1:gA2XjSMy3DrRdX9UqLuDtuVAAshb8bE1NhX1YK0Qe+8= @@ -1281,6 +1284,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.5.3 h1:3HUJmBFbQW9fhQOzMgseU134xfi6hU+mjWywx5Ty+/M= github.com/yuin/goldmark v1.5.3/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= @@ -1377,8 +1381,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.2.0 h1:BRXPfhNivWL5Yq0BGQ39a2sW6t44aODpfxkWjYdzewE= -golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= +golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1427,6 +1431,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1500,8 +1505,10 @@ golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1536,6 +1543,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1665,17 +1673,21 @@ golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1685,8 +1697,9 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1763,7 +1776,6 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1778,8 +1790,10 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4= +golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1914,8 +1928,8 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1 h1:jCw9YRd2s40X9Vxi4zKsPRvSPlHWNqadVkpbMsCPzPQ= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf h1:/JqRexUvugu6JURQ0O7RfV1EnvgrOxUV4tSjuAv0Sr0= +google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= @@ -1952,8 +1966,8 @@ google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -2075,14 +2089,16 @@ lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg= modernc.org/cc/v3 v3.32.4/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878= -modernc.org/cc/v3 v3.36.0 h1:0kmRkTmqNidmu3c7BNDSdVHCxXCkWLmWmCIVX4LUboo= modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= modernc.org/ccgo/v3 v3.9.2/go.mod h1:gnJpy6NIVqkETT+L5zPsQFj7L2kkhfPMzOghRNv/CFo= modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.6 h1:3l18poV+iUemQ98O3X5OMr97LOqlzis+ytivU4NqGhA= modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8= @@ -2097,36 +2113,43 @@ modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWC modernc.org/libc v1.9.5/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= -modernc.org/libc v1.16.7 h1:qzQtHhsZNpVPpeCu+aMIQldXeV1P0vRhSqCL0nOIJOA= modernc.org/libc v1.16.7/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0= +modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug= modernc.org/lldb v1.0.0/go.mod h1:jcRvJGWfCGodDZz8BPwiKMJxGJngQ/5DrRapkQnLob8= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8= modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= -modernc.org/memory v1.1.1 h1:bDOL0DIDLQv7bWhP3gMvIrnoFw+Eo6F7a2QK9HPDiFU= modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A= +modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= +modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/ql v1.0.0/go.mod h1:xGVyrLIatPcO2C1JvI/Co8c0sr6y91HKFNy4pt9JXEY= modernc.org/sortutil v1.1.0/go.mod h1:ZyL98OQHJgH9IEfN71VsamvJgrtRX9Dj2gX+vH86L1k= modernc.org/sqlite v1.10.6/go.mod h1:Z9FEjUtZP4qFEg6/SiADg9XCER7aYy9a/j7Pg9P7CPs= -modernc.org/sqlite v1.18.0 h1:ef66qJSgKeyLyrF4kQ2RHw/Ue3V89fyFNbGL073aDjI= modernc.org/sqlite v1.18.0/go.mod h1:B9fRWZacNxJBHoCJZQr1R54zhVn3fjfl0aszflrTSxY= +modernc.org/sqlite v1.20.1 h1:z6qRLw72B0VfRrJjs3l6hWkzYDx1bo0WGVrBGP4ohhM= +modernc.org/sqlite v1.20.1/go.mod h1:fODt+bFmc/j8LcoCbMSkAuKuGmhxjG45KGc25N2705M= modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= -modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs= modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo= -modernc.org/tcl v1.13.1 h1:npxzTwFTZYM8ghWicVIX1cRWzj7Nd8i6AqqX2p+IYao= modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= -modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk= +modernc.org/tcl v1.15.0 h1:oY+JeD11qVVSgVvodMJsu7Edf8tr5E/7tuhF5cNYz34= modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= -modernc.org/z v1.5.1 h1:RTNHdsrOpeoSeOF4FbzTo8gBYByaJ5xT7NgZ9ZqRiJM= modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= +modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE= modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/mattermost-plugin/product/api_adapter.go b/mattermost-plugin/product/api_adapter.go deleted file mode 100644 index 6f680f804..000000000 --- a/mattermost-plugin/product/api_adapter.go +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package product - -import ( - "database/sql" - - "github.com/gorilla/mux" - - "github.com/mattermost/mattermost-server/v6/app/request" - mm_model "github.com/mattermost/mattermost-server/v6/model" - "github.com/mattermost/mattermost-server/v6/shared/mlog" - - "github.com/mattermost/focalboard/server/model" -) - -// normalizeAppError returns a truly nil error if appErr is nil -// See https://golang.org/doc/faq#nil_error for more details. -func normalizeAppErr(appErr *mm_model.AppError) error { - if appErr == nil { - return nil - } - return appErr -} - -// serviceAPIAdapter is an adapter that flattens the APIs provided by suite services so they can -// be used as per the Plugin API. -// Note: when supporting a plugin build is no longer needed this adapter may be removed as the Boards app -// can be modified to use the services in modular fashion. -type serviceAPIAdapter struct { - api *boardsProduct - ctx *request.Context -} - -func newServiceAPIAdapter(api *boardsProduct) *serviceAPIAdapter { - return &serviceAPIAdapter{ - api: api, - ctx: request.EmptyContext(api.logger), - } -} - -// -// Channels service. -// - -func (a *serviceAPIAdapter) GetDirectChannel(userID1, userID2 string) (*mm_model.Channel, error) { - channel, appErr := a.api.channelService.GetDirectChannel(userID1, userID2) - return channel, normalizeAppErr(appErr) -} - -func (a *serviceAPIAdapter) GetDirectChannelOrCreate(userID1, userID2 string) (*mm_model.Channel, error) { - channel, appErr := a.api.channelService.GetDirectChannelOrCreate(userID1, userID2) - return channel, normalizeAppErr(appErr) -} - -func (a *serviceAPIAdapter) GetChannelByID(channelID string) (*mm_model.Channel, error) { - channel, appErr := a.api.channelService.GetChannelByID(channelID) - return channel, normalizeAppErr(appErr) -} - -func (a *serviceAPIAdapter) GetChannelMember(channelID string, userID string) (*mm_model.ChannelMember, error) { - member, appErr := a.api.channelService.GetChannelMember(channelID, userID) - return member, normalizeAppErr(appErr) -} - -func (a *serviceAPIAdapter) GetChannelsForTeamForUser(teamID string, userID string, includeDeleted bool) (mm_model.ChannelList, error) { - opts := &mm_model.ChannelSearchOpts{ - IncludeDeleted: includeDeleted, - } - channels, appErr := a.api.channelService.GetChannelsForTeamForUser(teamID, userID, opts) - return channels, normalizeAppErr(appErr) -} - -// -// Post service. -// - -func (a *serviceAPIAdapter) CreatePost(post *mm_model.Post) (*mm_model.Post, error) { - post, appErr := a.api.postService.CreatePost(a.ctx, post) - return post, normalizeAppErr(appErr) -} - -// -// User service. -// - -func (a *serviceAPIAdapter) GetUserByID(userID string) (*mm_model.User, error) { - user, appErr := a.api.userService.GetUser(userID) - return user, normalizeAppErr(appErr) -} - -func (a *serviceAPIAdapter) GetUserByUsername(name string) (*mm_model.User, error) { - user, appErr := a.api.userService.GetUserByUsername(name) - return user, normalizeAppErr(appErr) -} - -func (a *serviceAPIAdapter) GetUserByEmail(email string) (*mm_model.User, error) { - user, appErr := a.api.userService.GetUserByEmail(email) - return user, normalizeAppErr(appErr) -} - -func (a *serviceAPIAdapter) UpdateUser(user *mm_model.User) (*mm_model.User, error) { - user, appErr := a.api.userService.UpdateUser(a.ctx, user, true) - return user, normalizeAppErr(appErr) -} - -func (a *serviceAPIAdapter) GetUsersFromProfiles(options *mm_model.UserGetOptions) ([]*mm_model.User, error) { - user, appErr := a.api.userService.GetUsersFromProfiles(options) - return user, normalizeAppErr(appErr) -} - -// -// Team service. -// - -func (a *serviceAPIAdapter) GetTeamMember(teamID string, userID string) (*mm_model.TeamMember, error) { - member, appErr := a.api.teamService.GetMember(teamID, userID) - return member, normalizeAppErr(appErr) -} - -func (a *serviceAPIAdapter) CreateMember(teamID string, userID string) (*mm_model.TeamMember, error) { - member, appErr := a.api.teamService.CreateMember(a.ctx, teamID, userID) - return member, normalizeAppErr(appErr) -} - -// -// Permissions service. -// - -func (a *serviceAPIAdapter) HasPermissionTo(userID string, permission *mm_model.Permission) bool { - return a.api.permissionsService.HasPermissionTo(userID, permission) -} - -func (a *serviceAPIAdapter) HasPermissionToTeam(userID, teamID string, permission *mm_model.Permission) bool { - return a.api.permissionsService.HasPermissionToTeam(userID, teamID, permission) -} - -func (a *serviceAPIAdapter) HasPermissionToChannel(askingUserID string, channelID string, permission *mm_model.Permission) bool { - return a.api.permissionsService.HasPermissionToChannel(askingUserID, channelID, permission) -} - -// -// Bot service. -// - -func (a *serviceAPIAdapter) EnsureBot(bot *mm_model.Bot) (string, error) { - return a.api.botService.EnsureBot(a.ctx, boardsProductID, bot) -} - -// -// License service. -// - -func (a *serviceAPIAdapter) GetLicense() *mm_model.License { - return a.api.licenseService.GetLicense() -} - -// -// FileInfoStore service. -// - -func (a *serviceAPIAdapter) GetFileInfo(fileID string) (*mm_model.FileInfo, error) { - fi, appErr := a.api.fileInfoStoreService.GetFileInfo(fileID) - return fi, normalizeAppErr(appErr) -} - -// -// Cluster store. -// - -func (a *serviceAPIAdapter) PublishWebSocketEvent(event string, payload map[string]interface{}, broadcast *mm_model.WebsocketBroadcast) { - a.api.clusterService.PublishWebSocketEvent(boardsProductName, event, payload, broadcast) -} - -func (a *serviceAPIAdapter) PublishPluginClusterEvent(ev mm_model.PluginClusterEvent, opts mm_model.PluginClusterEventSendOptions) error { - return a.api.clusterService.PublishPluginClusterEvent(boardsProductName, ev, opts) -} - -// -// Cloud service. -// - -func (a *serviceAPIAdapter) GetCloudLimits() (*mm_model.ProductLimits, error) { - return a.api.cloudService.GetCloudLimits() -} - -// -// Config service. -// - -func (a *serviceAPIAdapter) GetConfig() *mm_model.Config { - return a.api.configService.Config() -} - -// -// Logger service. -// - -func (a *serviceAPIAdapter) GetLogger() mlog.LoggerIFace { - return a.api.logger -} - -// -// KVStore service. -// - -func (a *serviceAPIAdapter) KVSetWithOptions(key string, value []byte, options mm_model.PluginKVSetOptions) (bool, error) { - b, appErr := a.api.kvStoreService.SetPluginKeyWithOptions(boardsProductName, key, value, options) - return b, normalizeAppErr(appErr) -} - -// -// Store service. -// - -func (a *serviceAPIAdapter) GetMasterDB() (*sql.DB, error) { - return a.api.storeService.GetMasterDB(), nil -} - -// -// System service. -// - -func (a *serviceAPIAdapter) GetDiagnosticID() string { - return a.api.systemService.GetDiagnosticId() -} - -// -// Router service. -// - -func (a *serviceAPIAdapter) RegisterRouter(sub *mux.Router) { - a.api.routerService.RegisterRouter(boardsProductName, sub) -} - -// -// Preferences service. -// - -func (a *serviceAPIAdapter) GetPreferencesForUser(userID string) (mm_model.Preferences, error) { - p, appErr := a.api.preferencesService.GetPreferencesForUser(userID) - return p, normalizeAppErr(appErr) -} - -func (a *serviceAPIAdapter) UpdatePreferencesForUser(userID string, preferences mm_model.Preferences) error { - appErr := a.api.preferencesService.UpdatePreferencesForUser(userID, preferences) - return normalizeAppErr(appErr) -} - -func (a *serviceAPIAdapter) DeletePreferencesForUser(userID string, preferences mm_model.Preferences) error { - appErr := a.api.preferencesService.DeletePreferencesForUser(userID, preferences) - return normalizeAppErr(appErr) -} - -// Ensure the adapter implements ServicesAPI. -var _ model.ServicesAPI = &serviceAPIAdapter{} diff --git a/mattermost-plugin/product/boards_product.go b/mattermost-plugin/product/boards_product.go deleted file mode 100644 index 77230b863..000000000 --- a/mattermost-plugin/product/boards_product.go +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package product - -import ( - "errors" - "fmt" - - "github.com/mattermost/focalboard/mattermost-plugin/server/boards" - "github.com/mattermost/focalboard/server/model" - - mm_model "github.com/mattermost/mattermost-server/v6/model" - "github.com/mattermost/mattermost-server/v6/plugin" - "github.com/mattermost/mattermost-server/v6/product" - "github.com/mattermost/mattermost-server/v6/shared/mlog" -) - -const ( - boardsProductName = "boards" - boardsProductID = "com.mattermost.boards" -) - -var errServiceTypeAssert = errors.New("type assertion failed") - -func init() { - product.RegisterProduct(boardsProductName, product.Manifest{ - Initializer: newBoardsProduct, - Dependencies: map[product.ServiceKey]struct{}{ - product.TeamKey: {}, - product.ChannelKey: {}, - product.UserKey: {}, - product.PostKey: {}, - product.PermissionsKey: {}, - product.BotKey: {}, - product.ClusterKey: {}, - product.ConfigKey: {}, - product.LogKey: {}, - product.LicenseKey: {}, - product.FilestoreKey: {}, - product.FileInfoStoreKey: {}, - product.RouterKey: {}, - product.CloudKey: {}, - product.KVStoreKey: {}, - product.StoreKey: {}, - product.SystemKey: {}, - product.PreferencesKey: {}, - product.HooksKey: {}, - }, - }) -} - -type boardsProduct struct { - teamService product.TeamService - channelService product.ChannelService - userService product.UserService - postService product.PostService - permissionsService product.PermissionService - botService product.BotService - clusterService product.ClusterService - configService product.ConfigService - logger mlog.LoggerIFace - licenseService product.LicenseService - filestoreService product.FilestoreService - fileInfoStoreService product.FileInfoStoreService - routerService product.RouterService - cloudService product.CloudService - kvStoreService product.KVStoreService - storeService product.StoreService - systemService product.SystemService - preferencesService product.PreferencesService - hooksService product.HooksService - - boardsApp *boards.BoardsApp -} - -func newBoardsProduct(services map[product.ServiceKey]interface{}) (product.Product, error) { - boardsProd := &boardsProduct{} - - if err := populateServices(boardsProd, services); err != nil { - return nil, err - } - - boardsProd.logger.Info("Creating boards service") - - adapter := newServiceAPIAdapter(boardsProd) - boardsApp, err := boards.NewBoardsApp(adapter) - if err != nil { - return nil, fmt.Errorf("failed to create Boards service: %w", err) - } - - boardsProd.boardsApp = boardsApp - - // Add the Boards services API to the services map so other products can access Boards functionality. - boardsAPI := boards.NewBoardsServiceAPI(boardsApp) - services[product.BoardsKey] = boardsAPI - - return boardsProd, nil -} - -// populateServices populates the boardProduct with all the services needed from the suite. -func populateServices(boardsProd *boardsProduct, services map[product.ServiceKey]interface{}) error { - for key, service := range services { - switch key { - case product.TeamKey: - teamService, ok := service.(product.TeamService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.teamService = teamService - case product.ChannelKey: - channelService, ok := service.(product.ChannelService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.channelService = channelService - case product.UserKey: - userService, ok := service.(product.UserService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.userService = userService - case product.PostKey: - postService, ok := service.(product.PostService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.postService = postService - case product.PermissionsKey: - permissionsService, ok := service.(product.PermissionService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.permissionsService = permissionsService - case product.BotKey: - botService, ok := service.(product.BotService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.botService = botService - case product.ClusterKey: - clusterService, ok := service.(product.ClusterService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.clusterService = clusterService - case product.ConfigKey: - configService, ok := service.(product.ConfigService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.configService = configService - case product.LogKey: - logger, ok := service.(mlog.LoggerIFace) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.logger = logger.With(mlog.String("product", boardsProductName)) - case product.LicenseKey: - licenseService, ok := service.(product.LicenseService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.licenseService = licenseService - case product.FilestoreKey: - filestoreService, ok := service.(product.FilestoreService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.filestoreService = filestoreService - case product.FileInfoStoreKey: - fileInfoStoreService, ok := service.(product.FileInfoStoreService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.fileInfoStoreService = fileInfoStoreService - case product.RouterKey: - routerService, ok := service.(product.RouterService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.routerService = routerService - case product.CloudKey: - cloudService, ok := service.(product.CloudService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.cloudService = cloudService - case product.KVStoreKey: - kvStoreService, ok := service.(product.KVStoreService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.kvStoreService = kvStoreService - case product.StoreKey: - storeService, ok := service.(product.StoreService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.storeService = storeService - case product.SystemKey: - systemService, ok := service.(product.SystemService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.systemService = systemService - case product.PreferencesKey: - preferencesService, ok := service.(product.PreferencesService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.preferencesService = preferencesService - case product.HooksKey: - hooksService, ok := service.(product.HooksService) - if !ok { - return fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert) - } - boardsProd.hooksService = hooksService - } - } - return nil -} - -func (bp *boardsProduct) Start() error { - if !bp.configService.Config().FeatureFlags.BoardsProduct { - bp.logger.Info("Boards product disabled via feature flag") - return nil - } - - bp.logger.Info("Starting boards service") - - adapter := newServiceAPIAdapter(bp) - boardsApp, err := boards.NewBoardsApp(adapter) - if err != nil { - return fmt.Errorf("failed to create Boards service: %w", err) - } - - model.LogServerInfo(bp.logger) - - if err := bp.hooksService.RegisterHooks(boardsProductName, bp); err != nil { - return fmt.Errorf("failed to register hooks: %w", err) - } - - bp.boardsApp = boardsApp - if err := bp.boardsApp.Start(); err != nil { - return fmt.Errorf("failed to start Boards service: %w", err) - } - - return nil -} - -func (bp *boardsProduct) Stop() error { - bp.logger.Info("Stopping boards service") - - if bp.boardsApp == nil { - return nil - } - - if err := bp.boardsApp.Stop(); err != nil { - return fmt.Errorf("error while stopping Boards service: %w", err) - } - - return nil -} - -// -// These callbacks are called by the suite automatically -// - -func (bp *boardsProduct) OnConfigurationChange() error { - if bp.boardsApp == nil { - return nil - } - return bp.boardsApp.OnConfigurationChange() -} - -func (bp *boardsProduct) OnWebSocketConnect(webConnID, userID string) { - if bp.boardsApp == nil { - return - } - bp.boardsApp.OnWebSocketConnect(webConnID, userID) -} - -func (bp *boardsProduct) OnWebSocketDisconnect(webConnID, userID string) { - if bp.boardsApp == nil { - return - } - bp.boardsApp.OnWebSocketDisconnect(webConnID, userID) -} - -func (bp *boardsProduct) WebSocketMessageHasBeenPosted(webConnID, userID string, req *mm_model.WebSocketRequest) { - if bp.boardsApp == nil { - return - } - bp.boardsApp.WebSocketMessageHasBeenPosted(webConnID, userID, req) -} - -func (bp *boardsProduct) OnPluginClusterEvent(ctx *plugin.Context, ev mm_model.PluginClusterEvent) { - if bp.boardsApp == nil { - return - } - bp.boardsApp.OnPluginClusterEvent(ctx, ev) -} - -func (bp *boardsProduct) MessageWillBePosted(ctx *plugin.Context, post *mm_model.Post) (*mm_model.Post, string) { - if bp.boardsApp == nil { - return post, "" - } - return bp.boardsApp.MessageWillBePosted(ctx, post) -} - -func (bp *boardsProduct) MessageWillBeUpdated(ctx *plugin.Context, newPost, oldPost *mm_model.Post) (*mm_model.Post, string) { - if bp.boardsApp == nil { - return newPost, "" - } - return bp.boardsApp.MessageWillBeUpdated(ctx, newPost, oldPost) -} - -func (bp *boardsProduct) OnCloudLimitsUpdated(limits *mm_model.ProductLimits) { - if bp.boardsApp == nil { - return - } - bp.boardsApp.OnCloudLimitsUpdated(limits) -} - -func (bp *boardsProduct) RunDataRetention(nowTime, batchSize int64) (int64, error) { - if bp.boardsApp == nil { - return 0, nil - } - return bp.boardsApp.RunDataRetention(nowTime, batchSize) -} diff --git a/mattermost-plugin/product/imports/boards_imports.go b/mattermost-plugin/product/imports/boards_imports.go deleted file mode 100644 index 04b0ac70d..000000000 --- a/mattermost-plugin/product/imports/boards_imports.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package imports - -import ( - // Needed to ensure the init() method in the FocalBoard product is run. - // This file is copied to the mmserver imports package via makefile. - _ "github.com/mattermost/focalboard/mattermost-plugin/product" -) diff --git a/server/go.mod b/server/go.mod index 43d89004f..6f548eed7 100644 --- a/server/go.mod +++ b/server/go.mod @@ -10,7 +10,7 @@ require ( github.com/krolaw/zipstream v0.0.0-20180621105154-0a2661891f94 github.com/lib/pq v1.10.7 github.com/mattermost/mattermost-plugin-api v0.1.1 - github.com/mattermost/mattermost-server/v6 v6.0.0-20230116174708-240304ad0728 + github.com/mattermost/mattermost-server/v6 v6.0.0-20230321114510-b61c096497ac github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e github.com/mattn/go-sqlite3 v2.0.3+incompatible github.com/mgdelacroix/foundation v0.0.0-20220812143423-0bfc18f73538 @@ -57,7 +57,7 @@ require ( github.com/magiconair/properties v1.8.6 // indirect github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 // indirect github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d // indirect - github.com/mattermost/logr/v2 v2.0.15 // indirect + github.com/mattermost/logr/v2 v2.0.16 // indirect github.com/mattermost/squirrel v0.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect diff --git a/server/go.sum b/server/go.sum index a039930ec..7f06fadff 100644 --- a/server/go.sum +++ b/server/go.sum @@ -199,8 +199,8 @@ github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6 github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= @@ -482,8 +482,8 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= @@ -592,8 +592,8 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE= @@ -621,6 +621,7 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -651,8 +652,7 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/graph-gophers/graphql-go v1.4.0 h1:JE9wveRTSXwJyjdRd6bOQ7Ob5bewTUQ58Jv4OiVdpdE= -github.com/graph-gophers/graphql-go v1.4.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= +github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a h1:i0+Se9S+2zL5CBxJouqn2Ej6UQMwH1c57ZB6DVnqck4= github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -671,8 +671,7 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v1.3.1 h1:vDwF1DFNZhntP4DAjuTpOw3uEgMUpXh1pB5fW9DqHpo= -github.com/hashicorp/go-hclog v1.3.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.4.0 h1:ctuWFGrhFha8BnnzxqeRGidlEcQkDyL5u8J8t5eA11I= github.com/hashicorp/go-hclog v1.4.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= @@ -680,8 +679,7 @@ github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1: github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.4.6 h1:MDV3UrKQBM3du3G7MApDGvOsMYy3JQJ4exhSoKBAeVA= -github.com/hashicorp/go-plugin v1.4.6/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= +github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM= github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= @@ -804,13 +802,11 @@ github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdY github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= -github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.15.14 h1:i7WCKDToww0wA+9qrUZ1xOjp218vfFo3nTU6UHp+gOc= github.com/klauspost/compress v1.15.14/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.1 h1:U33DW0aiEj633gHYw3LoDNfkDiYnE5Q8M/TKJn2f2jI= -github.com/klauspost/cpuid/v2 v2.2.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -864,21 +860,12 @@ github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 h1:Khvh6waxG github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404/go.mod h1:RyS7FDNQlzF1PsjbJWHRI35exqaKGSO9qD4iv8QjE34= github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d h1:/RJ/UV7M5c7L2TQ0KNm4yZxxFvC1nvRz/gY/Daa35aI= github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d/go.mod h1:HLbgMEI5K131jpxGazJ97AxfPDt31osq36YS1oxFQPQ= -github.com/mattermost/logr/v2 v2.0.15 h1:+WNbGcsc3dBao65eXlceB6dTILNJRIrvubnsTl3zBew= -github.com/mattermost/logr/v2 v2.0.15/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg= -github.com/mattermost/mattermost-plugin-api v0.0.29-0.20220801143717-73008cfda2fb h1:q1qXKVv59rA2gcQ7lVLc5OlWBmfsR3i8mdGD5EZesyk= -github.com/mattermost/mattermost-plugin-api v0.0.29-0.20220801143717-73008cfda2fb/go.mod h1:PIeo40t9VTA4Wu1FwjzH7QmcgC3SRyk/ohCwJw4/oSo= +github.com/mattermost/logr/v2 v2.0.16 h1:jnePX4cPskC3WDFvUardh/xZfxNdsFXbEERJQ1kUEDE= +github.com/mattermost/logr/v2 v2.0.16/go.mod h1:1dm/YhTpozsqANXxo5Pi5zYLBsal2xY0pX+JZNbzYJY= +github.com/mattermost/mattermost-plugin-api v0.1.1 h1:bNnPbWCLWZpT/k2kjUxNnzCfUggU8WKs2ddz7hNjg1U= github.com/mattermost/mattermost-plugin-api v0.1.1/go.mod h1:9yZhtg0bBj3kqSTjXnjYBMZoTsWbe3ajdFMdl9/Jz34= -github.com/mattermost/mattermost-server/v6 v6.0.0-20220802151854-f07c31c5d933 h1:h7EibO8cwWeK8dLhC/A5tKGbkYSuJKZ0+2EXW7jDHoA= -github.com/mattermost/mattermost-server/v6 v6.0.0-20220802151854-f07c31c5d933/go.mod h1:otnBnKY9Y0eNkUKeD161de+BUBlESwANTnrkPT/392Y= -github.com/mattermost/mattermost-server/v6 v6.0.0-20221130200243-06e964b86b0d h1:CKJXDUCkRrfy1U9sZHOpvACOtkthV5iWt2boHUK720I= -github.com/mattermost/mattermost-server/v6 v6.0.0-20221130200243-06e964b86b0d/go.mod h1:U3gSM0I15WSMHPpDEU30mmc4JrbSDk+8F1+MFLOHWD0= -github.com/mattermost/mattermost-server/v6 v6.0.0-20221214122404-8d90c7042f93 h1:mGN2D6KhjKosQdZ+BHzmWxsA/tRK9FiR+nUd38nSZQY= -github.com/mattermost/mattermost-server/v6 v6.0.0-20221214122404-8d90c7042f93/go.mod h1:U3gSM0I15WSMHPpDEU30mmc4JrbSDk+8F1+MFLOHWD0= -github.com/mattermost/mattermost-server/v6 v6.0.0-20230116174708-240304ad0728 h1:fegj7GaXjiVH+/j1DsPtkobczafvUJynfFSwNeqIA84= -github.com/mattermost/mattermost-server/v6 v6.0.0-20230116174708-240304ad0728/go.mod h1:FPN2+SAU9ndEpMFcjClvdillSpvS2eQ+i1qiSgAUxPI= -github.com/mattermost/morph v0.0.0-20220401091636-39f834798da8 h1:gwliVjCTqAC01mSCNqa5nJ/4MmGq50vrjsottIhQ4d8= -github.com/mattermost/morph v0.0.0-20220401091636-39f834798da8/go.mod h1:jxM3g1bx+k2Thz7jofcHguBS8TZn5Pc+o5MGmORObhw= +github.com/mattermost/mattermost-server/v6 v6.0.0-20230321114510-b61c096497ac h1:AiV4kplzWpzuHvoh9Mfsy5FHOLRZA0cSIuFMg/32qqg= +github.com/mattermost/mattermost-server/v6 v6.0.0-20230321114510-b61c096497ac/go.mod h1:o61MGMh7We01wGr1ydGDA5mmNpjTzaBVWUAlezsgx50= github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e h1:VfNz+fvJ3DxOlALM22Eea8ONp5jHrybKBCcCtDPVlss= github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e/go.mod h1:xo0ljDknTpPxEdhhrUdwhLCexIsYyDKS6b41HqG8wGU= github.com/mattermost/squirrel v0.2.0 h1:8ZWeyf+MWQ2cL7hu9REZgLtz2IJi51qqZEovI3T3TT8= @@ -901,8 +888,8 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= @@ -925,8 +912,7 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.43 h1:14Q4lwblqTdlAmba05oq5xL0VBLHi06zS4yLnIkz6hI= -github.com/minio/minio-go/v7 v7.0.43/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw= +github.com/minio/minio-go/v7 v7.0.45 h1:g4IeM9M9pW/Lo8AGGNOjBZYlvmtlE1N5TQEYWXRWzIs= github.com/minio/minio-go/v7 v7.0.45/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= @@ -1045,8 +1031,7 @@ github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= -github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= @@ -1109,11 +1094,10 @@ github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa h1:tEkEyxYeZ43TR55QU/hsIt9aRGBxbgGuz9CGykjvogY= github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -1245,8 +1229,7 @@ github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= -github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw= -github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= @@ -1254,8 +1237,7 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw= -github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= +github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -1280,7 +1262,6 @@ github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9 github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -github.com/wiggin77/merror v1.0.2/go.mod h1:uQTcIU0Z6jRK4OwqganPYerzQxSFJ4GSHM3aurxxQpg= github.com/wiggin77/merror v1.0.4 h1:XxFLEevmQQfgJW2AxhapuMG7C1fQqfbim/XyUmYv/ZM= github.com/wiggin77/merror v1.0.4/go.mod h1:H2ETSu7/bPE0Ymf4bEwdUoo73OOEkdClnoRisfw0Nm0= github.com/wiggin77/srslog v1.0.1 h1:gA2XjSMy3DrRdX9UqLuDtuVAAshb8bE1NhX1YK0Qe+8= @@ -1304,9 +1285,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.12 h1:6hffw6vALvEDqJ19dOJvJKOoAOKe4NDaTqvd2sktGN0= -github.com/yuin/goldmark v1.4.12/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.5.3 h1:3HUJmBFbQW9fhQOzMgseU134xfi6hU+mjWywx5Ty+/M= github.com/yuin/goldmark v1.5.3/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= @@ -1402,8 +1382,7 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.2.0 h1:BRXPfhNivWL5Yq0BGQ39a2sW6t44aODpfxkWjYdzewE= -golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1453,6 +1432,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1526,11 +1506,9 @@ golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220614195744-fb05da6f9022 h1:0qjDla5xICC2suMtyRH/QqX3B1btXTfNsIt/i4LFgO0= -golang.org/x/net v0.0.0-20220614195744-fb05da6f9022/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1566,9 +1544,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1698,16 +1675,13 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 h1:PgOr27OhUx2IRqGJ2RxAWI4dJQ7bi9cSrB82uzFzfUA= -golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1724,9 +1698,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1804,7 +1777,6 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1819,18 +1791,15 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY= -golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4= golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= @@ -1960,8 +1929,7 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1 h1:jCw9YRd2s40X9Vxi4zKsPRvSPlHWNqadVkpbMsCPzPQ= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf h1:/JqRexUvugu6JURQ0O7RfV1EnvgrOxUV4tSjuAv0Sr0= google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= @@ -1999,8 +1967,7 @@ google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -2123,7 +2090,6 @@ lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg= modernc.org/cc/v3 v3.32.4/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878= -modernc.org/cc/v3 v3.36.0 h1:0kmRkTmqNidmu3c7BNDSdVHCxXCkWLmWmCIVX4LUboo= modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= @@ -2131,11 +2097,9 @@ modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpN modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= modernc.org/ccgo/v3 v3.9.2/go.mod h1:gnJpy6NIVqkETT+L5zPsQFj7L2kkhfPMzOghRNv/CFo= modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.6 h1:3l18poV+iUemQ98O3X5OMr97LOqlzis+ytivU4NqGhA= modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= -modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8= @@ -2150,46 +2114,43 @@ modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWC modernc.org/libc v1.9.5/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= -modernc.org/libc v1.16.7 h1:qzQtHhsZNpVPpeCu+aMIQldXeV1P0vRhSqCL0nOIJOA= modernc.org/libc v1.16.7/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0= modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug= modernc.org/lldb v1.0.0/go.mod h1:jcRvJGWfCGodDZz8BPwiKMJxGJngQ/5DrRapkQnLob8= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8= modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= -modernc.org/memory v1.1.1 h1:bDOL0DIDLQv7bWhP3gMvIrnoFw+Eo6F7a2QK9HPDiFU= modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A= modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/ql v1.0.0/go.mod h1:xGVyrLIatPcO2C1JvI/Co8c0sr6y91HKFNy4pt9JXEY= modernc.org/sortutil v1.1.0/go.mod h1:ZyL98OQHJgH9IEfN71VsamvJgrtRX9Dj2gX+vH86L1k= modernc.org/sqlite v1.10.6/go.mod h1:Z9FEjUtZP4qFEg6/SiADg9XCER7aYy9a/j7Pg9P7CPs= -modernc.org/sqlite v1.18.0 h1:ef66qJSgKeyLyrF4kQ2RHw/Ue3V89fyFNbGL073aDjI= modernc.org/sqlite v1.18.0/go.mod h1:B9fRWZacNxJBHoCJZQr1R54zhVn3fjfl0aszflrTSxY= +modernc.org/sqlite v1.20.1 h1:z6qRLw72B0VfRrJjs3l6hWkzYDx1bo0WGVrBGP4ohhM= modernc.org/sqlite v1.20.1/go.mod h1:fODt+bFmc/j8LcoCbMSkAuKuGmhxjG45KGc25N2705M= modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= -modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs= modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo= -modernc.org/tcl v1.13.1 h1:npxzTwFTZYM8ghWicVIX1cRWzj7Nd8i6AqqX2p+IYao= modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= -modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk= +modernc.org/tcl v1.15.0 h1:oY+JeD11qVVSgVvodMJsu7Edf8tr5E/7tuhF5cNYz34= modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= -modernc.org/z v1.5.1 h1:RTNHdsrOpeoSeOF4FbzTo8gBYByaJ5xT7NgZ9ZqRiJM= modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= +modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE= modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/server/services/store/storetests/boards.go b/server/services/store/storetests/boards.go index e5e82d597..b7ae5cc7b 100644 --- a/server/services/store/storetests/boards.go +++ b/server/services/store/storetests/boards.go @@ -778,6 +778,9 @@ func testDeleteMember(t *testing.T, store store.Store) { require.NoError(t, err) initialMemberHistory := len(memberHistory) + // wait to avoid hitting pk uniqueness constraint in history + time.Sleep(1 * time.Millisecond) + require.NoError(t, store.DeleteMember(boardID, userID)) rbm, err := store.GetMemberForBoard(boardID, userID) From a76ef9c1685e21283718d3a6d8cd688ab8be5e2d Mon Sep 17 00:00:00 2001 From: zhsj Date: Fri, 2 Jun 2023 00:37:43 +0800 Subject: [PATCH 058/102] Fix Chinese lang code (#4415) zh-cn is for Simplified Chinese, and zh-tw is for Traditional Chinese. And remove invalid zh-tx code. Co-authored-by: Mattermod Co-authored-by: Mattermost Build --- webapp/src/constants.ts | 6 +++--- webapp/src/i18n.tsx | 4 +--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/webapp/src/constants.ts b/webapp/src/constants.ts index f750d5e81..e5e1f4cea 100644 --- a/webapp/src/constants.ts +++ b/webapp/src/constants.ts @@ -111,12 +111,12 @@ class Constants { displayName: 'Pусский', }, { - code: 'zh-cn', - name: 'chinese', + code: 'zh-tw', + name: 'traditional-chinese', displayName: '中文 (繁體)', }, { - code: 'zh-tw', + code: 'zh-cn', name: 'simplified-chinese', displayName: '中文 (简体)', }, diff --git a/webapp/src/i18n.tsx b/webapp/src/i18n.tsx index 6768916eb..5779c9d49 100644 --- a/webapp/src/i18n.tsx +++ b/webapp/src/i18n.tsx @@ -54,11 +54,9 @@ export function getMessages(lang: string): {[key: string]: string} { case 'tr': return messages_tr case 'zh-cn': - return messages_zhHant - case 'zh-tx': return messages_zhHans case 'zh-tw': - return messages_zhHans + return messages_zhHant } return messages_en } From d95d100d8caf9bc164cd167e0a25f1db37332397 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Wed, 7 Jun 2023 15:39:44 -0700 Subject: [PATCH 059/102] Fix boards share dialog (#4761) --- .../shareBoard/teamPermissionsRow.tsx | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/webapp/src/components/shareBoard/teamPermissionsRow.tsx b/webapp/src/components/shareBoard/teamPermissionsRow.tsx index 2650e7790..7f16f8e1d 100644 --- a/webapp/src/components/shareBoard/teamPermissionsRow.tsx +++ b/webapp/src/components/shareBoard/teamPermissionsRow.tsx @@ -47,19 +47,22 @@ const TeamPermissionsRow = (): JSX.Element => { } } - let currentRoleName = intl.formatMessage({id: 'BoardMember.schemeNone', defaultMessage: 'None'}) - if (board.type === BoardTypeOpen && board.minimumRole === MemberRole.Admin) { - currentRoleName = intl.formatMessage({id: 'BoardMember.schemeAdmin', defaultMessage: 'Admin'}) - } else if (board.type === BoardTypeOpen && board.minimumRole === MemberRole.Editor) { - if (board.isTemplate) { + let currentRoleName = intl.formatMessage({id: 'BoardMember.schemeAdmin', defaultMessage: 'Admin'}) + if (board.type === BoardTypeOpen) { + currentRoleName = intl.formatMessage({id: 'BoardMember.schemeEditor', defaultMessage: 'Editor'}) + if (board.minimumRole === MemberRole.Editor) { + if (board.isTemplate) { + currentRoleName = intl.formatMessage({id: 'BoardMember.schemeViewer', defaultMessage: 'Viewer'}) + } else { + currentRoleName = intl.formatMessage({id: 'BoardMember.schemeEditor', defaultMessage: 'Editor'}) + } + } else if (board.minimumRole === MemberRole.Commenter) { + currentRoleName = intl.formatMessage({id: 'BoardMember.schemeCommenter', defaultMessage: 'Commenter'}) + } else if (board.minimumRole === MemberRole.Viewer) { currentRoleName = intl.formatMessage({id: 'BoardMember.schemeViewer', defaultMessage: 'Viewer'}) - } else { - currentRoleName = intl.formatMessage({id: 'BoardMember.schemeEditor', defaultMessage: 'Editor'}) } - } else if (board.type === BoardTypeOpen && board.minimumRole === MemberRole.Commenter) { - currentRoleName = intl.formatMessage({id: 'BoardMember.schemeCommenter', defaultMessage: 'Commenter'}) - } else if (board.type === BoardTypeOpen && board.minimumRole === MemberRole.Viewer) { - currentRoleName = intl.formatMessage({id: 'BoardMember.schemeViewer', defaultMessage: 'Viewer'}) + } else { + currentRoleName = intl.formatMessage({id: 'BoardMember.schemeNone', defaultMessage: 'None'}) } const confirmationDialog = ( From 3b7954872e37d766bd1929e36b82e4a42e917dd8 Mon Sep 17 00:00:00 2001 From: Miguel de la Cruz Date: Thu, 8 Jun 2023 18:33:59 +0200 Subject: [PATCH 060/102] Upgrade Scorecards action version (#4760) --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index a457bdc37..c8e127052 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -27,7 +27,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@c8416b0b2bf627c349ca92fc8e3de51a64b005cf # v1.0.2 + uses: ossf/scorecard-action@80e868c13c90f172d68d1f4501dee99e2479f7af # v2.1.3 with: results_file: results.sarif results_format: sarif From c4454cac5242bae7da16c8173c35db5e4b87a750 Mon Sep 17 00:00:00 2001 From: Miguel de la Cruz Date: Fri, 9 Jun 2023 18:44:15 +0200 Subject: [PATCH 061/102] Update ubuntu version to use latest LTS (#4771) --- .github/workflows/ci.yml | 4 ++-- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/dev-release.yml | 4 ++-- .github/workflows/lint-server.yml | 4 ++-- .github/workflows/prod-release.yml | 4 ++-- .github/workflows/scorecards-analysis.yml | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2b0052bf9..cd68bb3b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ env: jobs: ci-ubuntu-server: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: matrix: @@ -39,7 +39,7 @@ jobs: run: cd focalboard; make server-test-${{matrix['db']}} ci-ubuntu-webapp: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - name: Checkout uses: actions/checkout@v3 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 48f67c744..54f768eda 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -17,7 +17,7 @@ jobs: permissions: security-events: write # for github/codeql-action/autobuild to send a status report name: Analyze - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: fail-fast: false diff --git a/.github/workflows/dev-release.yml b/.github/workflows/dev-release.yml index 17dcba2d3..eb9c83f64 100644 --- a/.github/workflows/dev-release.yml +++ b/.github/workflows/dev-release.yml @@ -14,7 +14,7 @@ env: jobs: ubuntu: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 with: @@ -172,7 +172,7 @@ jobs: path: ${{ github.workspace }}/focalboard/win-wpf/dist/focalboard-win.zip plugin: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/lint-server.yml b/.github/workflows/lint-server.yml index 88bf97b6c..44d6374de 100644 --- a/.github/workflows/lint-server.yml +++ b/.github/workflows/lint-server.yml @@ -13,7 +13,7 @@ env: jobs: down-migrations: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 with: @@ -26,7 +26,7 @@ jobs: golangci: name: plugin - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - uses: actions/setup-go@v3 with: diff --git a/.github/workflows/prod-release.yml b/.github/workflows/prod-release.yml index 05df6126c..e0f1fafed 100644 --- a/.github/workflows/prod-release.yml +++ b/.github/workflows/prod-release.yml @@ -9,7 +9,7 @@ env: jobs: ubuntu: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - name: Checkout @@ -171,7 +171,7 @@ jobs: path: ${{ github.workspace }}/focalboard/win-wpf/dist/focalboard-win.zip plugin-release: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - name: Checkout diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index c8e127052..f94e34d3b 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -13,7 +13,7 @@ permissions: read-all jobs: analysis: name: Scorecards analysis - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 permissions: # Needed to upload the results to code-scanning dashboard. security-events: write From 343b7bdc4bcf1e9e2eaa85b2c72d20a867806085 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Tue, 20 Jun 2023 03:36:13 -0600 Subject: [PATCH 062/102] check 'path' for 'empty' as well (#4785) --- server/app/files.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/app/files.go b/server/app/files.go index b45726756..627912107 100644 --- a/server/app/files.go +++ b/server/app/files.go @@ -15,6 +15,8 @@ import ( "github.com/mattermost/mattermost-server/v6/shared/mlog" ) +const emptyString = "empty" + var errEmptyFilename = errors.New("IsFileArchived: empty filename not allowed") var ErrFileNotFound = errors.New("file not found") @@ -102,7 +104,7 @@ func (a *App) GetFilePath(teamID, rootID, fileName string) (*mm_model.FileInfo, var filePath string - if fileInfo != nil && fileInfo.Path != "" { + if fileInfo != nil && fileInfo.Path != "" && fileInfo.Path != emptyString { filePath = fileInfo.Path } else { filePath = filepath.Join(teamID, rootID, fileName) From 625526c3e781b6eb716a7ea1036d28a0eed6f373 Mon Sep 17 00:00:00 2001 From: Miguel de la Cruz Date: Thu, 22 Jun 2023 11:31:08 +0200 Subject: [PATCH 063/102] Updates import to read with a scanner (#4788) * Updates import to read with a scanner * Fix linter --- server/app/import.go | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/server/app/import.go b/server/app/import.go index 7ea99cd87..2852c0e3e 100644 --- a/server/app/import.go +++ b/server/app/import.go @@ -20,12 +20,14 @@ import ( ) const ( - archiveVersion = 2 - legacyFileBegin = "{\"version\":1" + archiveVersion = 2 + legacyFileBegin = "{\"version\":1" + importMaxFileSize = 1024 * 1024 * 70 ) var ( - errBlockIsNotABoard = errors.New("block is not a board") + errBlockIsNotABoard = errors.New("block is not a board") + errSizeLimitExceeded = errors.New("size limit exceeded") ) // ImportArchive imports an archive containing zero or more boards, plus all @@ -153,7 +155,8 @@ func (a *App) ImportBoardJSONL(r io.Reader, opt model.ImportArchiveOptions) (*mo Blocks: make([]*model.Block, 0, 10), Boards: make([]*model.Board, 0, 10), } - lineReader := bufio.NewReader(r) + lineReader := &io.LimitedReader{R: r, N: importMaxFileSize + 1} + scanner := bufio.NewScanner(lineReader) userID := opt.ModifiedBy if userID == model.SingleUser { @@ -165,8 +168,12 @@ func (a *App) ImportBoardJSONL(r io.Reader, opt model.ImportArchiveOptions) (*mo lineNum := 1 firstLine := true - for { - line, errRead := readLine(lineReader) + for scanner.Scan() { + if lineReader.N <= 0 { + return nil, fmt.Errorf("error parsing archive line %d: %w", lineNum, errSizeLimitExceeded) + } + + line := bytes.TrimSpace(scanner.Bytes()) if len(line) != 0 { var skip bool if firstLine { @@ -233,14 +240,10 @@ func (a *App) ImportBoardJSONL(r io.Reader, opt model.ImportArchiveOptions) (*mo firstLine = false } } + } - if errRead != nil { - if errors.Is(errRead, io.EOF) { - break - } - return nil, fmt.Errorf("error reading archive line %d: %w", lineNum, errRead) - } - lineNum++ + if errRead := scanner.Err(); errRead != nil { + return nil, fmt.Errorf("error reading archive line %d: %w", lineNum, errRead) } // loop to remove the people how are not part of the team and system @@ -462,9 +465,3 @@ func parseVersionFile(r io.Reader) (int, error) { } return header.Version, nil } - -func readLine(r *bufio.Reader) ([]byte, error) { - line, err := r.ReadBytes('\n') - line = bytes.TrimSpace(line) - return line, err -} From 5dfd402e2679e6da32073aacb863867e6e64ee04 Mon Sep 17 00:00:00 2001 From: Miguel de la Cruz Date: Mon, 26 Jun 2023 21:37:37 +0200 Subject: [PATCH 064/102] Unify and enhance block validation (#4790) * Adds limit check for block titles * Adds limit check for the aggregation of the fields * Fix linter * Adds tests * Fix err check method order --- server/api/api_test.go | 2 + server/model/block.go | 37 ++++++++ server/model/error.go | 30 ++++-- server/services/store/sqlstore/blocks.go | 22 +---- .../services/store/sqlstore/legacy_blocks.go | 2 +- server/services/store/storetests/blocks.go | 95 +++++++++++++++++++ .../store/storetests/boards_and_blocks.go | 71 +++++++++++++- 7 files changed, 231 insertions(+), 28 deletions(-) diff --git a/server/api/api_test.go b/server/api/api_test.go index 27639a107..74b90ffc8 100644 --- a/server/api/api_test.go +++ b/server/api/api_test.go @@ -31,6 +31,8 @@ func TestErrorResponse(t *testing.T) { {"ErrInvalidCategory", model.NewErrInvalidCategory("open"), http.StatusBadRequest, "open"}, {"ErrBoardMemberIsLastAdmin", model.ErrBoardMemberIsLastAdmin, http.StatusBadRequest, "no admins"}, {"ErrBoardIDMismatch", model.ErrBoardIDMismatch, http.StatusBadRequest, "Board IDs do not match"}, + {"ErrBlockTitleSizeLimitExceeded", model.ErrBlockTitleSizeLimitExceeded, http.StatusBadRequest, "block title size limit exceeded"}, + {"ErrBlockFieldsSizeLimitExceeded", model.ErrBlockFieldsSizeLimitExceeded, http.StatusBadRequest, "block fields size limit exceeded"}, // unauthorized {"ErrUnauthorized", model.NewErrUnauthorized("not enough permissions"), http.StatusUnauthorized, "not enough permissions"}, diff --git a/server/model/block.go b/server/model/block.go index 9e1658ec6..538c64856 100644 --- a/server/model/block.go +++ b/server/model/block.go @@ -2,12 +2,26 @@ package model import ( "encoding/json" + "errors" "io" "strconv" + "unicode/utf8" "github.com/mattermost/focalboard/server/services/audit" ) +const ( + BlockTitleMaxBytes = 65535 // Maximum size of a TEXT column in MySQL + BlockTitleMaxRunes = BlockTitleMaxBytes / 4 // Assume a worst-case representation + BlockFieldsMaxRunes = 800000 +) + +var ( + ErrBlockEmptyBoardID = errors.New("boardID is empty") + ErrBlockTitleSizeLimitExceeded = errors.New("block title size limit exceeded") + ErrBlockFieldsSizeLimitExceeded = errors.New("block fields size limit exceeded") +) + // Block is the basic data unit // swagger:model type Block struct { @@ -124,6 +138,29 @@ func BlocksFromJSON(data io.Reader) []*Block { return blocks } +// IsValid checks the block for errors before inserting, and makes +// sure it complies with the requirements of a valid block. +func (b *Block) IsValid() error { + if b.BoardID == "" { + return ErrBlockEmptyBoardID + } + + if utf8.RuneCountInString(b.Title) > BlockTitleMaxRunes { + return ErrBlockTitleSizeLimitExceeded + } + + fieldsJSON, err := json.Marshal(b.Fields) + if err != nil { + return err + } + + if utf8.RuneCountInString(string(fieldsJSON)) > BlockFieldsMaxRunes { + return ErrBlockFieldsSizeLimitExceeded + } + + return nil +} + // LogClone implements the `mlog.LogCloner` interface to provide a subset of Block fields for logging. func (b *Block) LogClone() interface{} { return struct { diff --git a/server/model/error.go b/server/model/error.go index 71af6cf45..d85f599c1 100644 --- a/server/model/error.go +++ b/server/model/error.go @@ -166,7 +166,9 @@ func (ni *ErrNotImplemented) Error() string { // - model.ErrAuthParam // - model.ErrInvalidCategory // - model.ErrBoardMemberIsLastAdmin -// - model.ErrBoardIDMismatch. +// - model.ErrBoardIDMismatch +// - model.ErrBlockTitleSizeLimitExceeded +// - model.ErrBlockFieldsSizeLimitExceeded. func IsErrBadRequest(err error) bool { if err == nil { return false @@ -178,14 +180,14 @@ func IsErrBadRequest(err error) bool { return true } - // check if this is a model.ErrAuthParam - var ap *ErrAuthParam - if errors.As(err, &ap) { + // check if this is a model.ErrViewsLimitReached + if errors.Is(err, ErrViewsLimitReached) { return true } - // check if this is a model.ErrViewsLimitReached - if errors.Is(err, ErrViewsLimitReached) { + // check if this is a model.ErrAuthParam + var ap *ErrAuthParam + if errors.As(err, &ap) { return true } @@ -195,13 +197,23 @@ func IsErrBadRequest(err error) bool { return true } - // check if this is a model.ErrBoardIDMismatch + // check if this is a model.ErrBoardMemberIsLastAdmin if errors.Is(err, ErrBoardMemberIsLastAdmin) { return true } - // check if this is a model.ErrBoardMemberIsLastAdmin - return errors.Is(err, ErrBoardIDMismatch) + // check if this is a model.ErrBoardIDMismatch + if errors.Is(err, ErrBoardIDMismatch) { + return true + } + + // check if this is a model.ErrBlockTitleSizeLimitExceeded + if errors.Is(err, ErrBlockTitleSizeLimitExceeded) { + return true + } + + // check if this is a model.ErrBlockTitleSizeLimitExceeded + return errors.Is(err, ErrBlockFieldsSizeLimitExceeded) } // IsErrUnauthorized returns true if `err` is or wraps one of: diff --git a/server/services/store/sqlstore/blocks.go b/server/services/store/sqlstore/blocks.go index 306815a18..a22daddb7 100644 --- a/server/services/store/sqlstore/blocks.go +++ b/server/services/store/sqlstore/blocks.go @@ -20,18 +20,6 @@ const ( descClause = " DESC " ) -type ErrEmptyBoardID struct{} - -func (re ErrEmptyBoardID) Error() string { - return "boardID is empty" -} - -type ErrLimitExceeded struct{ max int } - -func (le ErrLimitExceeded) Error() string { - return fmt.Sprintf("limit exceeded (max=%d)", le.max) -} - func (s *SQLStore) timestampToCharField(name string, as string) string { switch s.dbType { case model.MysqlDBType: @@ -240,8 +228,8 @@ func (s *SQLStore) blocksFromRows(rows *sql.Rows) ([]*model.Block, error) { } func (s *SQLStore) insertBlock(db sq.BaseRunner, block *model.Block, userID string) error { - if block.BoardID == "" { - return ErrEmptyBoardID{} + if err := block.IsValid(); err != nil { + return fmt.Errorf("error validating block %s: %w", block.ID, err) } fieldsJSON, err := json.Marshal(block.Fields) @@ -348,8 +336,8 @@ func (s *SQLStore) patchBlocks(db sq.BaseRunner, blockPatches *model.BlockPatchB func (s *SQLStore) insertBlocks(db sq.BaseRunner, blocks []*model.Block, userID string) error { for _, block := range blocks { - if block.BoardID == "" { - return ErrEmptyBoardID{} + if err := block.IsValid(); err != nil { + return fmt.Errorf("error validating block %s: %w", block.ID, err) } } for i := range blocks { @@ -1018,7 +1006,7 @@ func (s *SQLStore) deleteBlockChildren(db sq.BaseRunner, boardID string, parentI func (s *SQLStore) undeleteBlockChildren(db sq.BaseRunner, boardID string, parentID string, modifiedBy string) error { if boardID == "" { - return ErrEmptyBoardID{} + return model.ErrBlockEmptyBoardID } where := fmt.Sprintf("board_id='%s'", boardID) diff --git a/server/services/store/sqlstore/legacy_blocks.go b/server/services/store/sqlstore/legacy_blocks.go index 842f2d258..418daa97a 100644 --- a/server/services/store/sqlstore/legacy_blocks.go +++ b/server/services/store/sqlstore/legacy_blocks.go @@ -162,7 +162,7 @@ func (s *SQLStore) getLegacyBlock(db sq.BaseRunner, workspaceID string, blockID //nolint:unused func (s *SQLStore) insertLegacyBlock(db sq.BaseRunner, workspaceID string, block *model.Block, userID string) error { if block.BoardID == "" { - return ErrEmptyBoardID{} + return model.ErrBlockEmptyBoardID } fieldsJSON, err := json.Marshal(block.Fields) diff --git a/server/services/store/storetests/blocks.go b/server/services/store/storetests/blocks.go index bbd01ef72..50e659ac8 100644 --- a/server/services/store/storetests/blocks.go +++ b/server/services/store/storetests/blocks.go @@ -3,6 +3,7 @@ package storetests import ( "math" "strconv" + "strings" "testing" "time" @@ -142,6 +143,35 @@ func testInsertBlock(t *testing.T, store store.Store) { require.Len(t, blocks, initialCount+1) }) + t.Run("block with title too large", func(t *testing.T) { + block := &model.Block{ + ID: "id-test", + BoardID: boardID, + ModifiedBy: userID, + Title: strings.Repeat("A", model.BlockTitleMaxRunes+1), + } + + err := store.InsertBlock(block, "user-id-1") + require.ErrorIs(t, err, model.ErrBlockTitleSizeLimitExceeded) + }) + + t.Run("block with aggregated fields size too large", func(t *testing.T) { + block := &model.Block{ + ID: "id-test", + BoardID: boardID, + ModifiedBy: userID, + Fields: map[string]any{ + "one": strings.Repeat("1", model.BlockFieldsMaxRunes/4), + "two": strings.Repeat("2", model.BlockFieldsMaxRunes/4), + "three": strings.Repeat("3", model.BlockFieldsMaxRunes/4), + "four": strings.Repeat("4", model.BlockFieldsMaxRunes/4), + }, + } + + err := store.InsertBlock(block, "user-id-2") + require.ErrorIs(t, err, model.ErrBlockFieldsSizeLimitExceeded) + }) + t.Run("insert new block", func(t *testing.T) { block := &model.Block{ BoardID: testBoardID, @@ -184,6 +214,71 @@ func testInsertBlock(t *testing.T, store store.Store) { require.Equal(t, "New Title", newBlock.Title) }) + t.Run("update existing block with title too large", func(t *testing.T) { + block := &model.Block{ + ID: "id-3", + BoardID: "board-id-1", + CreatedBy: "user-id-3", + Title: "New Title", + } + + // inserting + err := store.InsertBlock(block, "user-id-3") + require.NoError(t, err) + + // created by populated from user id for new blocks + require.Equal(t, "user-id-3", block.CreatedBy) + + // hack to avoid multiple, quick updates to a card + // violating block_history composite primary key constraint + time.Sleep(1 * time.Millisecond) + + // updating + newBlock := &model.Block{ + ID: "id-3", + BoardID: "board-id-1", + CreatedBy: "user-id-3", + Title: strings.Repeat("A", model.BlockTitleMaxRunes+1), + } + err = store.InsertBlock(newBlock, "user-id-3") + require.ErrorIs(t, err, model.ErrBlockTitleSizeLimitExceeded) + }) + + t.Run("update existing block with aggregated fields size too large", func(t *testing.T) { + block := &model.Block{ + ID: "id-3", + BoardID: "board-id-1", + CreatedBy: "user-id-3", + Title: "New Title", + } + + // inserting + err := store.InsertBlock(block, "user-id-3") + require.NoError(t, err) + + // created by populated from user id for new blocks + require.Equal(t, "user-id-3", block.CreatedBy) + + // hack to avoid multiple, quick updates to a card + // violating block_history composite primary key constraint + time.Sleep(1 * time.Millisecond) + + // updating + newBlock := &model.Block{ + ID: "id-3", + BoardID: "board-id-1", + CreatedBy: "user-id-3", + Fields: map[string]any{ + "one": strings.Repeat("1", model.BlockFieldsMaxRunes/4), + "two": strings.Repeat("2", model.BlockFieldsMaxRunes/4), + "three": strings.Repeat("3", model.BlockFieldsMaxRunes/4), + "four": strings.Repeat("4", model.BlockFieldsMaxRunes/4), + }, + } + err = store.InsertBlock(newBlock, "user-id-3") + require.ErrorIs(t, err, model.ErrBlockFieldsSizeLimitExceeded) + }) + createdAt, err := time.Parse(time.RFC822, "01 Jan 90 01:00 IST") assert.NoError(t, err) diff --git a/server/services/store/storetests/boards_and_blocks.go b/server/services/store/storetests/boards_and_blocks.go index f780005e6..e5b715353 100644 --- a/server/services/store/storetests/boards_and_blocks.go +++ b/server/services/store/storetests/boards_and_blocks.go @@ -2,6 +2,7 @@ package storetests import ( "fmt" + "strings" "testing" "time" @@ -141,6 +142,30 @@ func testCreateBoardsAndBlocks(t *testing.T, store store.Store) { require.Empty(t, bab) require.Empty(t, members) }) + + t.Run("should apply block size limits", func(t *testing.T) { + // one of the blocks is invalid as it has a title too large + newBab := &model.BoardsAndBlocks{ + Boards: []*model.Board{ + {ID: "board-id-7", TeamID: teamID, Type: model.BoardTypeOpen}, + {ID: "board-id-8", TeamID: teamID, Type: model.BoardTypePrivate}, + {ID: "board-id-9", TeamID: teamID, Type: model.BoardTypeOpen}, + }, + Blocks: []*model.Block{ + {ID: "block-id-5", BoardID: "board-id-7", Type: model.TypeCard}, + {ID: "block-id-6", BoardID: "board-id-8", Type: model.TypeCard, Title: strings.Repeat("A", model.BlockTitleMaxRunes+1)}, + }, + } + + bab, err := store.CreateBoardsAndBlocks(newBab, userID) + require.ErrorIs(t, err, model.ErrBlockTitleSizeLimitExceeded) + require.Nil(t, bab) + + bab, members, err := store.CreateBoardsAndBlocksWithAdmin(newBab, userID) + require.ErrorIs(t, err, model.ErrBlockTitleSizeLimitExceeded) + require.Empty(t, bab) + require.Empty(t, members) + }) } func testPatchBoardsAndBlocks(t *testing.T, store store.Store) { @@ -190,7 +215,7 @@ func testPatchBoardsAndBlocks(t *testing.T, store store.Store) { require.Error(t, err) require.Nil(t, bab) - // check that things have changed + // check that things have not changed rBoard, err := store.GetBoard("board-id-1") require.NoError(t, err) require.Equal(t, initialTitle, rBoard.Title) @@ -200,6 +225,50 @@ func testPatchBoardsAndBlocks(t *testing.T, store store.Store) { require.Equal(t, initialTitle, rBlock.Title) }) + t.Run("should apply block size limits", func(t *testing.T) { + if store.DBType() == model.SqliteDBType { + t.Skip("No transactions support int sqlite") + } + + initialTitle := "initial title" + newTitle := strings.Repeat("A", model.BlockTitleMaxRunes+1) + + board := &model.Board{ + ID: "board-id-1", + Title: initialTitle, + TeamID: teamID, + Type: model.BoardTypeOpen, + } + _, err := store.InsertBoard(board, userID) + require.NoError(t, err) + + block := &model.Block{ + ID: "block-id-1", + BoardID: "board-id-1", + Title: initialTitle, + } + require.NoError(t, store.InsertBlock(block, userID)) + + // apply the patches + pbab := &model.PatchBoardsAndBlocks{ + BlockIDs: []string{"block-id-1"}, + BlockPatches: []*model.BlockPatch{ + {Title: &newTitle}, + }, + } + + time.Sleep(10 * time.Millisecond) + + bab, err := store.PatchBoardsAndBlocks(pbab, userID) + require.ErrorIs(t, err, model.ErrBlockTitleSizeLimitExceeded) + require.Nil(t, bab) + + // check that things have not changed + rBlock, err := store.GetBlock("block-id-1") + require.NoError(t, err) + require.Equal(t, initialTitle, rBlock.Title) + }) + t.Run("patch boards and blocks", func(t *testing.T) { newBab := &model.BoardsAndBlocks{ Boards: []*model.Board{ From 5bea58c2c3faf4d0af8a687f15dab8f932f2cc67 Mon Sep 17 00:00:00 2001 From: Felipe Nogueira Date: Thu, 6 Apr 2023 18:03:54 +0200 Subject: [PATCH 065/102] Translated using Weblate (Portuguese) Currently translated at 20.4% (94 of 460 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/pt/ Translated using Weblate (Portuguese) Currently translated at 11.5% (52 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/pt/ Translated using Weblate (Portuguese (Brazil)) Currently translated at 99.1% (446 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/pt_BR/ Translated using Weblate (Portuguese (Brazil)) Currently translated at 96.4% (434 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/pt_BR/ --- webapp/i18n/pt.json | 60 ++++++++++++++++++++++++++++++++++++++++++ webapp/i18n/pt_BR.json | 47 +++++++++++++++++++-------------- 2 files changed, 87 insertions(+), 20 deletions(-) diff --git a/webapp/i18n/pt.json b/webapp/i18n/pt.json index 975ddbc47..6f70f2608 100644 --- a/webapp/i18n/pt.json +++ b/webapp/i18n/pt.json @@ -1,4 +1,5 @@ { + "AdminBadge.SystemAdmin": "Administrador", "AppBar.Tooltip": "Alternar quadros vinculados", "Attachment.Attachment-title": "Anexo", "AttachmentBlock.DeleteAction": "Apagar", @@ -9,6 +10,7 @@ "AttachmentBlock.uploadSuccess": "Anexo carregado.", "AttachmentElement.delete-confirmation-dialog-button-text": "Apagar", "AttachmentElement.download": "Baixar", + "BoardComponent.add-a-group": "+ Adicionar um grupo", "BoardComponent.delete": "Apagar", "BoardComponent.hidden-columns": "Colunas escondidas", "BoardComponent.hide": "Esconder", @@ -19,6 +21,7 @@ "BoardMember.schemeCommenter": "Comentador", "BoardMember.schemeEditor": "Editor", "BoardMember.schemeNone": "Nenhum", + "BoardMember.unlinkChannel": "Desvincular", "BoardPage.newVersion": "Está disponível uma nova versão do Boards, clique aqui para recarregar.", "BoardPage.syncFailed": "O Board pode ter sido apagado ou o acesso revogado.", "BoardTemplateSelector.add-template": "Criar novo modelo", @@ -29,7 +32,64 @@ "BoardTemplateSelector.title": "Criar um board", "BoardTemplateSelector.use-this-template": "Usar este modelo", "BoardsSwitcher.Title": "Encontrar boards", + "Calculations.Options.average.displayName": "Média", "Calculations.Options.average.label": "Média", + "Calculations.Options.countUniqueValue.displayName": "Único", + "Calculations.Options.countValue.displayName": "Valores", + "Calculations.Options.dateRange.displayName": "Intervalo", + "Calculations.Options.dateRange.label": "Intervalo", + "Calculations.Options.latest.label": "Mais recente", + "Calculations.Options.max.displayName": "Máx", + "Calculations.Options.max.label": "Máximo", + "Calculations.Options.min.displayName": "Mínimo", + "Calculations.Options.min.label": "Mínimo", + "Calculations.Options.none.label": "Nenhum", + "Calculations.Options.range.displayName": "Intervalo", + "Calculations.Options.range.label": "Intervalo", + "Calculations.Options.sum.displayName": "Soma", + "Calculations.Options.sum.label": "Soma", + "CalendarCard.untitled": "Sem título", + "CardActionsMenu.copiedLink": "Copiado!", + "CardActionsMenu.copyLink": "Copiar link", + "CardActionsMenu.delete": "Apagar", + "CardActionsMenu.duplicate": "Duplicar", + "CardBadges.title-comments": "Comentários", + "CardDetail.Attach": "Anexar", + "CardDetail.Follow": "Seguir", + "CardDetail.Following": "Seguindo", + "CardDetail.add-content": "Adicionar conteúdo", + "CardDetail.add-icon": "Adicionar ícone", + "CardDetail.add-property": "+ Adicionar uma propriedade", + "CardDetail.limited-button": "Atualizar", + "CardDetail.new-comment-placeholder": "Adicionar um comentário...", + "CardDetailProperty.delete-action-button": "Apagar", + "CardDialog.delete-confirmation-dialog-button-text": "Apagar", + "Categories.CreateCategoryDialog.CancelText": "Cancelar", + "Categories.CreateCategoryDialog.CreateText": "Criar", + "Categories.CreateCategoryDialog.UpdateText": "Atualizar", + "CenterPanel.Login": "Entrar", + "CenterPanel.Share": "Compartilhar", + "Comment.delete": "Apagar", + "CommentsList.send": "Enviar", + "ConfirmPerson.empty": "Vazio", + "ConfirmPerson.search": "Procurar...", + "ConfirmationDialog.cancel-action": "Cancelar", + "ConfirmationDialog.confirm-action": "Confirmar", + "ContentBlock.Delete": "Apagar", + "ContentBlock.DeleteAction": "apagar", + "ContentBlock.addElement": "adicionar {type}", + "ContentBlock.editText": "Editar texto...", + "ContentBlock.image": "imagem", + "ContentBlock.moveDown": "Mover pra baixo", + "ContentBlock.moveUp": "Mover pra cima", + "ContentBlock.text": "texto", + "DateFilter.empty": "Vazio", + "DateRange.clear": "Limpar", + "DateRange.empty": "Vazio", + "DateRange.today": "Hoje", + "DeleteBoardDialog.confirm-cancel": "Cancelar", + "DeleteBoardDialog.confirm-delete": "Apagar", + "EditableDayPicker.today": "Hoje", "shareBoard.members-select-group": "Membros", "shareBoard.unknown-channel-display-name": "Canal desconhecido", "tutorial_tip.ok": "Próximo" diff --git a/webapp/i18n/pt_BR.json b/webapp/i18n/pt_BR.json index 8e984b4b5..cb0f44a96 100644 --- a/webapp/i18n/pt_BR.json +++ b/webapp/i18n/pt_BR.json @@ -1,11 +1,14 @@ { "AppBar.Tooltip": "Ativar boards vinculados", "Attachment.Attachment-title": "Anexo", - "AttachmentBlock.DeleteAction": "apagar", + "AttachmentBlock.DeleteAction": "excluir", "AttachmentBlock.addElement": "adicionar {type}", "AttachmentBlock.delete": "Anexo apagado.", + "AttachmentBlock.failed": "Este arquivo não pôde ser carregado pois ultrapassou o tamanho limite.", + "AttachmentBlock.upload": "Carregando anexo.", "AttachmentBlock.uploadSuccess": "Anexo enviado.", - "AttachmentElement.delete-confirmation-dialog-button-text": "Apagar", + "AttachmentElement.delete-confirmation-dialog-button-text": "Excluir", + "AttachmentElement.download": "Baixar", "AttachmentElement.upload-percentage": "Enviando...({uploadPercent}%)", "BoardComponent.add-a-group": "+ Adicione um grupo", "BoardComponent.delete": "Excluir", @@ -13,7 +16,7 @@ "BoardComponent.hide": "Ocultar", "BoardComponent.new": "Novo", "BoardComponent.no-property": "Sem {property}", - "BoardComponent.no-property-title": "Itens com um {property} vazio irão aqui. Esta coluna não pode ser removida.", + "BoardComponent.no-property-title": "Itens com um {property} vazio estarão aqui. Esta coluna não pode ser removida.", "BoardComponent.show": "Exibir", "BoardMember.schemeAdmin": "Administrador", "BoardMember.schemeCommenter": "Comentarista", @@ -85,7 +88,7 @@ "CardDetail.add-icon": "Adicionar ícone", "CardDetail.add-property": "+ Adicionar propriedade", "CardDetail.addCardText": "adicionar texto ao card", - "CardDetail.limited-body": "Atualize para nosso plano Professional ou Enterprise para visualizar cartões arquivados, ter visualizações ilimitadas por quadros, cartões ilimitados e mais.", + "CardDetail.limited-body": "Atualize para nosso plano Professional ou Enterprise.", "CardDetail.limited-button": "Upgrade", "CardDetail.limited-title": "Este cartão está oculto", "CardDetail.moveContent": "Mover conteúdo do cartão", @@ -100,10 +103,11 @@ "CardDetailProperty.property-deleted": "{propertyName} excluído com êxito!", "CardDetailProperty.property-name-change-subtext": "digite de \"{oldPropType}\" para \"{newPropType}\"", "CardDetial.limited-link": "Saiba mais sobre nossos planos.", + "CardDialog.delete-confirmation-dialog-attachment": "Confirmar exclusão de anexo", "CardDialog.delete-confirmation-dialog-button-text": "Excluir", "CardDialog.delete-confirmation-dialog-heading": "Confirmar exclusão do cartão", "CardDialog.editing-template": "Você está editando um template.", - "CardDialog.nocard": "Esse card não existe ou não está acessível.", + "CardDialog.nocard": "Esse cartão não existe ou não está acessível.", "Categories.CreateCategoryDialog.CancelText": "Cancelar", "Categories.CreateCategoryDialog.CreateText": "Criar", "Categories.CreateCategoryDialog.Placeholder": "Nomeie sua categoria", @@ -125,11 +129,12 @@ "ContentBlock.checkbox": "caixa de seleção", "ContentBlock.divider": "Divisor", "ContentBlock.editCardCheckbox": "Caixa de seleção marcada", - "ContentBlock.editCardCheckboxText": "editar texto do card", - "ContentBlock.editCardText": "editar texto do card", + "ContentBlock.editCardCheckboxText": "editar texto do cartão", + "ContentBlock.editCardText": "editar texto do cartão", "ContentBlock.editText": "Editar texto...", "ContentBlock.image": "imagem", "ContentBlock.insertAbove": "Inserir acima", + "ContentBlock.moveBlock": "mover conteúdo do cartão", "ContentBlock.moveDown": "Mover para baixo", "ContentBlock.moveUp": "Mover para cima", "ContentBlock.text": "texto", @@ -139,7 +144,7 @@ "DateRange.today": "Hoje", "DeleteBoardDialog.confirm-cancel": "Cancelar", "DeleteBoardDialog.confirm-delete": "Excluir", - "DeleteBoardDialog.confirm-info": "Tem certeza que você quer deletar um board \"{boardTitle}\"? Excluir irá apagar todos os cards no board.", + "DeleteBoardDialog.confirm-info": "Tem certeza que quer excluir o quadro \"{boardTitle}\"? Excluí-lo irá apagar todos os cartões no quadro.", "DeleteBoardDialog.confirm-info-template": "Tem certeza que deseja excluir o board template “{boardTitle}”?", "DeleteBoardDialog.confirm-tite": "Confirmar exclusão do board", "DeleteBoardDialog.confirm-tite-template": "Confirmar exclusão do template de board", @@ -176,20 +181,20 @@ "KanbanCard.untitled": "Sem nome", "MentionSuggestion.is-not-board-member": "(não membro do board)", "Mutator.new-board-from-template": "novo board do template", - "Mutator.new-card-from-template": "novo card à partir de um template", - "Mutator.new-template-from-card": "novo template à partir de um card", + "Mutator.new-card-from-template": "novo cartão à partir de um template", + "Mutator.new-template-from-card": "novo template à partir de um cartão", "OnboardingTour.AddComments.Body": "Você pode comentar questões, e até mesmo @mencionar seus usuários companheiros de Mattermost para conseguir suas atenções.", "OnboardingTour.AddComments.Title": "Adicionar comentários", "OnboardingTour.AddDescription.Body": "Adicione uma descrição para que seus companheiros de time saibam sobre o que é o cartão.", "OnboardingTour.AddDescription.Title": "Adicionar descrição", - "OnboardingTour.AddProperties.Body": "Adicione várias propriedades aos cartões para torna-los mais poderosos!", + "OnboardingTour.AddProperties.Body": "Adicione várias propriedades aos cartões para torná-los mais poderosos.", "OnboardingTour.AddProperties.Title": "Adicionar propriedades", "OnboardingTour.AddView.Body": "Crie uma nova view aquei para organizar seu board usando diferentes layouts.", "OnboardingTour.AddView.Title": "Adicionar nova visualização", "OnboardingTour.CopyLink.Body": "Você pode compartilhar seus cartões com companheiros de times copiando e colando o link em um canal, mensagem direta, ou mensagem de grupo.", "OnboardingTour.CopyLink.Title": "Copiar link", "OnboardingTour.OpenACard.Body": "Abra um cartão para explorar formas poderosas que os Boards podem ajudar a organizar seu trabalho.", - "OnboardingTour.OpenACard.Title": "Abrir um card", + "OnboardingTour.OpenACard.Title": "Abrir um cartão", "OnboardingTour.ShareBoard.Body": "Você pode compartilhar seu board internament, com seu time, ou public para permitir visibilidade fora da sua organização.", "OnboardingTour.ShareBoard.Title": "Compartilhar quadro", "PersonProperty.board-members": "Membros do Board", @@ -249,6 +254,7 @@ "Sidebar.invite-users": "Convidar usuários", "Sidebar.logout": "Sair", "Sidebar.new-category.badge": "Novo", + "Sidebar.new-category.drag-boards-cta": "Solte quadros aqui...", "Sidebar.no-boards-in-category": "Nenhum board", "Sidebar.product-tour": "Tour pelo produto", "Sidebar.random-icons": "Ícones aleatórios", @@ -283,6 +289,7 @@ "TableHeaderMenu.insert-right": "Inserir à direita", "TableHeaderMenu.sort-ascending": "Ordem ascendente", "TableHeaderMenu.sort-descending": "Ordem descendente", + "TableRow.DuplicateCard": "duplicar cartão", "TableRow.MoreOption": "Mais ações", "TableRow.open": "Abrir", "TopBar.give-feedback": "Dar feedback", @@ -315,7 +322,7 @@ "ViewHeader.delete-template": "Excluir", "ViewHeader.display-by": "Exibir por: {property}", "ViewHeader.edit-template": "Editar", - "ViewHeader.empty-card": "Card vazio", + "ViewHeader.empty-card": "Cartão vazio", "ViewHeader.export-board-archive": "Exportar arquivo do painel", "ViewHeader.export-complete": "Exportação completa!", "ViewHeader.export-csv": "Exportar para CSV", @@ -325,7 +332,7 @@ "ViewHeader.new": "Novo", "ViewHeader.properties": "Propriedades", "ViewHeader.properties-menu": "Menu de propriedades", - "ViewHeader.search-text": "Pesquisar cards", + "ViewHeader.search-text": "Pesquisar cartões", "ViewHeader.select-a-template": "Selecionar um modelo", "ViewHeader.set-default-template": "Definir como padrão", "ViewHeader.sort": "Ordenar", @@ -335,9 +342,9 @@ "ViewLimitDialog.Heading": "Limite de views por board alcaçado", "ViewLimitDialog.PrimaryButton.Title.Admin": "Upgrade", "ViewLimitDialog.PrimaryButton.Title.RegularUser": "Notificar Admin", - "ViewLimitDialog.Subtext.Admin": "Atualize para nosso plano Profissional ou Enterprise para ter visualizações ilimitados por boards, cards ilimitados e mais.", + "ViewLimitDialog.Subtext.Admin": "Atualize para nosso plano Profissional ou Enterprise.", "ViewLimitDialog.Subtext.Admin.PricingPageLink": "Saiba mais sobre nossos planos.", - "ViewLimitDialog.Subtext.RegularUser": "Nofique seu Admin para atualizar para nosso plano Professional ou Enterprise para ter visualizações ilimitadas, cards ilimitados e mais.", + "ViewLimitDialog.Subtext.RegularUser": "Notifique seu administrador para atualizar para nosso plano Professional ou Enterprise.", "ViewLimitDialog.UpgradeImg.AltText": "Atualizar imagem", "ViewLimitDialog.notifyAdmin.Success": "Seu administrador foi notificado", "ViewTitle.hide-description": "esconder descrição", @@ -383,7 +390,7 @@ "guest-no-board.subtitle": "Você não tem acesso a nenhum board neste time ainda, por favor aguarde até alguém adicionar você a algum board.", "guest-no-board.title": "Nenhum board ainda", "imagePaste.upload-failed": "Alguns arquivos não foram enviados. Tamanho limite alcançado", - "limitedCard.title": "Cards ocultos", + "limitedCard.title": "Cartões ocultos", "login.log-in-button": "Entrar", "login.log-in-title": "Entrar", "login.register-button": "ou criar uma conta se você ainda não tiver uma", @@ -394,15 +401,15 @@ "notification-box-card-limit-reached.close-tooltip": "Soneca por 10 dias", "notification-box-card-limit-reached.contact-link": "notificar seu admin", "notification-box-card-limit-reached.link": "Atualizar para um plano pago", - "notification-box-card-limit-reached.title": "{cards} cards ocultos do board", - "notification-box-cards-hidden.title": "Esta ação ocultou outro card", + "notification-box-card-limit-reached.title": "{cards} cartões ocultos do board", + "notification-box-cards-hidden.title": "Esta ação ocultou outro cartão", "notification-box.card-limit-reached.not-admin.text": "Para acessar cartões arquivados, você pode {contactLink} para atualizar para um plano pago.", "notification-box.card-limit-reached.text": "Limite de cartão alcançado, para visualizar cartões mais antigos, {link}", "person.add-user-to-board": "Adicionar {username} ao board", "person.add-user-to-board-confirm-button": "Adicionar ao board", "person.add-user-to-board-permissions": "Permissões", "person.add-user-to-board-question": "Você quer adicionar {username} ao board?", - "person.add-user-to-board-warning": "{username} não é um membro de um board, e não será notificado.", + "person.add-user-to-board-warning": "", "register.login-button": "ou entre se você já tem uma conta", "register.signup-title": "Registrar uma conta", "rhs-board-non-admin-msg": "Você não é um adminstrador do quadro", From d69c5bee0ea9d1311ae62f431e1a682a2249b1d6 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Thu, 6 Apr 2023 18:03:55 +0200 Subject: [PATCH 066/102] Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/ Update translation files Updated by "Remove blank strings" hook in Weblate. Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/ --- webapp/i18n/ar.json | 1 - webapp/i18n/de.json | 1 - webapp/i18n/en_AU.json | 1 - webapp/i18n/fr.json | 1 - webapp/i18n/he.json | 1 - webapp/i18n/hr.json | 1 - webapp/i18n/hu.json | 1 - webapp/i18n/it.json | 1 - webapp/i18n/ja.json | 1 - webapp/i18n/ka.json | 1 - webapp/i18n/ko.json | 1 - webapp/i18n/nb_NO.json | 1 - webapp/i18n/nl.json | 1 - webapp/i18n/pl.json | 1 - webapp/i18n/pt_BR.json | 2 -- webapp/i18n/ru.json | 1 - webapp/i18n/sk.json | 1 - webapp/i18n/sv.json | 1 - webapp/i18n/tr.json | 1 - webapp/i18n/uk.json | 1 - webapp/i18n/zh_Hans.json | 1 - webapp/i18n/zh_Hant.json | 1 - 22 files changed, 23 deletions(-) diff --git a/webapp/i18n/ar.json b/webapp/i18n/ar.json index 8eeca566e..622352141 100644 --- a/webapp/i18n/ar.json +++ b/webapp/i18n/ar.json @@ -112,7 +112,6 @@ "Categories.CreateCategoryDialog.UpdateText": "تحديث", "CenterPanel.Login": "تسجيل الدخول", "CenterPanel.Share": "مشاركة", - "CloudMessage.cloud-server": "احصل علي خادم سحابي خاص بك مجاني.", "ColorOption.selectColor": "اختر {color} اللون", "Comment.delete": "حذف", "CommentsList.send": "إرسال", diff --git a/webapp/i18n/de.json b/webapp/i18n/de.json index cfcee4b6f..c085d2f7c 100644 --- a/webapp/i18n/de.json +++ b/webapp/i18n/de.json @@ -115,7 +115,6 @@ "CenterPanel.Login": "Anmeldung", "CenterPanel.Share": "Teilen", "ChannelIntro.CreateBoard": "Erstelle ein Board", - "CloudMessage.cloud-server": "Hole deine eigenen freien Cloud Server.", "ColorOption.selectColor": "Wähle Farbe {color}", "Comment.delete": "Löschen", "CommentsList.send": "Abschicken", diff --git a/webapp/i18n/en_AU.json b/webapp/i18n/en_AU.json index d3f396fb4..8165346f7 100644 --- a/webapp/i18n/en_AU.json +++ b/webapp/i18n/en_AU.json @@ -115,7 +115,6 @@ "CenterPanel.Login": "Login", "CenterPanel.Share": "Share", "ChannelIntro.CreateBoard": "Create a board", - "CloudMessage.cloud-server": "Get your own free cloud server.", "ColorOption.selectColor": "Select {color} Colour", "Comment.delete": "Delete", "CommentsList.send": "Send", diff --git a/webapp/i18n/fr.json b/webapp/i18n/fr.json index b790d973a..ad55293a0 100644 --- a/webapp/i18n/fr.json +++ b/webapp/i18n/fr.json @@ -102,7 +102,6 @@ "Categories.CreateCategoryDialog.UpdateText": "Mettre à jour", "CenterPanel.Login": "Connexion", "CenterPanel.Share": "Partager", - "CloudMessage.cloud-server": "Obtenez votre propre serveur cloud gratuitement.", "ColorOption.selectColor": "Choisir la couleur {color}", "Comment.delete": "Supprimer", "CommentsList.send": "Envoyer", diff --git a/webapp/i18n/he.json b/webapp/i18n/he.json index 3ba148877..692ec27fb 100644 --- a/webapp/i18n/he.json +++ b/webapp/i18n/he.json @@ -101,7 +101,6 @@ "Categories.CreateCategoryDialog.UpdateText": "עדכון", "CenterPanel.Login": "כניסה", "CenterPanel.Share": "שיתוף", - "CloudMessage.cloud-server": "קבל שרת ענן בחינם.", "ColorOption.selectColor": "בחירת צבע {color}", "Comment.delete": "מחיקה", "CommentsList.send": "שליחה", diff --git a/webapp/i18n/hr.json b/webapp/i18n/hr.json index fb61549d1..24236441c 100644 --- a/webapp/i18n/hr.json +++ b/webapp/i18n/hr.json @@ -115,7 +115,6 @@ "CenterPanel.Login": "Prijava", "CenterPanel.Share": "Dijeli", "ChannelIntro.CreateBoard": "Stvori ploču", - "CloudMessage.cloud-server": "Nabavi vlastiti besplatni poslužitelj u oblaku.", "ColorOption.selectColor": "Odaberi boju {color}", "Comment.delete": "Izbriši", "CommentsList.send": "Pošalji", diff --git a/webapp/i18n/hu.json b/webapp/i18n/hu.json index d1107c36c..e83514485 100644 --- a/webapp/i18n/hu.json +++ b/webapp/i18n/hu.json @@ -114,7 +114,6 @@ "Categories.CreateCategoryDialog.UpdateText": "Frissítés", "CenterPanel.Login": "Bejelentkezés", "CenterPanel.Share": "Megosztás", - "CloudMessage.cloud-server": "Szerezze be saját ingyenes felhőszerverét.", "ColorOption.selectColor": "{color} szín kiválasztása", "Comment.delete": "Törlés", "CommentsList.send": "Küldés", diff --git a/webapp/i18n/it.json b/webapp/i18n/it.json index cb31d20f8..ce133950b 100644 --- a/webapp/i18n/it.json +++ b/webapp/i18n/it.json @@ -100,7 +100,6 @@ "Categories.CreateCategoryDialog.UpdateText": "Aggiorna", "CenterPanel.Login": "Login", "CenterPanel.Share": "Condividi", - "CloudMessage.cloud-server": "Ottieni il tuo server cloud gratuito.", "ColorOption.selectColor": "Seleziona{color} Colore", "Comment.delete": "Elimina", "CommentsList.send": "Invia", diff --git a/webapp/i18n/ja.json b/webapp/i18n/ja.json index 695793325..a4eae6f69 100644 --- a/webapp/i18n/ja.json +++ b/webapp/i18n/ja.json @@ -115,7 +115,6 @@ "CenterPanel.Login": "ログイン", "CenterPanel.Share": "共有", "ChannelIntro.CreateBoard": "Boardを作成する", - "CloudMessage.cloud-server": "専用の無料クラウドサーバーを入手する。", "ColorOption.selectColor": "{color} 色を選択", "Comment.delete": "削除", "CommentsList.send": "送信", diff --git a/webapp/i18n/ka.json b/webapp/i18n/ka.json index 1741695fe..5623cbd56 100644 --- a/webapp/i18n/ka.json +++ b/webapp/i18n/ka.json @@ -102,7 +102,6 @@ "Categories.CreateCategoryDialog.UpdateText": "განახლება", "CenterPanel.Login": "შესვლა", "CenterPanel.Share": "გაზიარება", - "CloudMessage.cloud-server": "მიიღეთ თქვენი საკუთარი უფასო Cloud სერვერი.", "ColorOption.selectColor": "აირჩიეთ {color} ფერი", "Comment.delete": "წაშლა", "CommentsList.send": "გაგზავნა", diff --git a/webapp/i18n/ko.json b/webapp/i18n/ko.json index 03577f36c..3e622dda5 100644 --- a/webapp/i18n/ko.json +++ b/webapp/i18n/ko.json @@ -114,7 +114,6 @@ "Categories.CreateCategoryDialog.UpdateText": "업데이트", "CenterPanel.Login": "로그인", "CenterPanel.Share": "공유", - "CloudMessage.cloud-server": "무료 클라우드 서버를 구입하십시오.", "ColorOption.selectColor": "{color} 색 선택하기", "Comment.delete": "삭제하기", "CommentsList.send": "보내기", diff --git a/webapp/i18n/nb_NO.json b/webapp/i18n/nb_NO.json index 604a40885..3dc682e13 100644 --- a/webapp/i18n/nb_NO.json +++ b/webapp/i18n/nb_NO.json @@ -115,7 +115,6 @@ "CenterPanel.Login": "Logg inn", "CenterPanel.Share": "Del", "ChannelIntro.CreateBoard": "Opprett tavle", - "CloudMessage.cloud-server": "Få din egen gratis skytjener.", "ColorOption.selectColor": "Velg {color} farge", "Comment.delete": "Slett", "CommentsList.send": "Send", diff --git a/webapp/i18n/nl.json b/webapp/i18n/nl.json index e06b492ac..d0d735c94 100644 --- a/webapp/i18n/nl.json +++ b/webapp/i18n/nl.json @@ -115,7 +115,6 @@ "CenterPanel.Login": "Aanmelden", "CenterPanel.Share": "Delen", "ChannelIntro.CreateBoard": "Een bord aanmaken", - "CloudMessage.cloud-server": "Krijg jouw eigen gratis cloud server.", "ColorOption.selectColor": "Selecteer {color} Kleur", "Comment.delete": "Verwijderen", "CommentsList.send": "Verzenden", diff --git a/webapp/i18n/pl.json b/webapp/i18n/pl.json index 956f2dca4..903d7112e 100644 --- a/webapp/i18n/pl.json +++ b/webapp/i18n/pl.json @@ -115,7 +115,6 @@ "CenterPanel.Login": "Logowanie", "CenterPanel.Share": "Udostępnij", "ChannelIntro.CreateBoard": "Utwórz tablicę", - "CloudMessage.cloud-server": "Uzyskaj własny, bezpłatny serwer w chmurze.", "ColorOption.selectColor": "Wybierz Kolor {color}", "Comment.delete": "Usuń", "CommentsList.send": "Wyślij", diff --git a/webapp/i18n/pt_BR.json b/webapp/i18n/pt_BR.json index cb0f44a96..ce693bab5 100644 --- a/webapp/i18n/pt_BR.json +++ b/webapp/i18n/pt_BR.json @@ -115,7 +115,6 @@ "CenterPanel.Login": "Login", "CenterPanel.Share": "Compartilhar", "ChannelIntro.CreateBoard": "Criar um board", - "CloudMessage.cloud-server": "Obtenha seu próprio cloud server de graça.", "ColorOption.selectColor": "Selecione {color} Cor", "Comment.delete": "Excluir", "CommentsList.send": "Enviar", @@ -409,7 +408,6 @@ "person.add-user-to-board-confirm-button": "Adicionar ao board", "person.add-user-to-board-permissions": "Permissões", "person.add-user-to-board-question": "Você quer adicionar {username} ao board?", - "person.add-user-to-board-warning": "", "register.login-button": "ou entre se você já tem uma conta", "register.signup-title": "Registrar uma conta", "rhs-board-non-admin-msg": "Você não é um adminstrador do quadro", diff --git a/webapp/i18n/ru.json b/webapp/i18n/ru.json index f6b502b65..bcbcbdf89 100644 --- a/webapp/i18n/ru.json +++ b/webapp/i18n/ru.json @@ -115,7 +115,6 @@ "CenterPanel.Login": "Логин", "CenterPanel.Share": "Поделиться", "ChannelIntro.CreateBoard": "Создать доску", - "CloudMessage.cloud-server": "Получите свой бесплатный облачный сервер.", "ColorOption.selectColor": "Выберите цвет {color}", "Comment.delete": "Удалить", "CommentsList.send": "Отправить", diff --git a/webapp/i18n/sk.json b/webapp/i18n/sk.json index 7d5945f89..6f3c5f222 100644 --- a/webapp/i18n/sk.json +++ b/webapp/i18n/sk.json @@ -113,7 +113,6 @@ "CenterPanel.Login": "Prihlásiť sa", "CenterPanel.Share": "Zdieľať", "ChannelIntro.CreateBoard": "Vytvoriť nástenku", - "CloudMessage.cloud-server": "Získajte vlastný cloudový server zadarmo.", "ColorOption.selectColor": "Vyberte {color} farbu", "Comment.delete": "Odstrániť", "CommentsList.send": "Odoslať", diff --git a/webapp/i18n/sv.json b/webapp/i18n/sv.json index dbea552e4..d776db6a9 100644 --- a/webapp/i18n/sv.json +++ b/webapp/i18n/sv.json @@ -115,7 +115,6 @@ "CenterPanel.Login": "Logga in", "CenterPanel.Share": "Dela", "ChannelIntro.CreateBoard": "Skapa en board", - "CloudMessage.cloud-server": "Skaffa din egen molnserver gratis.", "ColorOption.selectColor": "Välj {color} färg", "Comment.delete": "Radera", "CommentsList.send": "Skicka", diff --git a/webapp/i18n/tr.json b/webapp/i18n/tr.json index b3d14b065..3c071a3f6 100644 --- a/webapp/i18n/tr.json +++ b/webapp/i18n/tr.json @@ -115,7 +115,6 @@ "CenterPanel.Login": "Oturum aç", "CenterPanel.Share": "Paylaş", "ChannelIntro.CreateBoard": "Bir pano ekle", - "CloudMessage.cloud-server": "Kendi ücretsiz bulut sunucunuzu edinin.", "ColorOption.selectColor": "{color} rengi seçin", "Comment.delete": "Sil", "CommentsList.send": "Gönder", diff --git a/webapp/i18n/uk.json b/webapp/i18n/uk.json index b27fd6e0c..3e4f7d7cd 100644 --- a/webapp/i18n/uk.json +++ b/webapp/i18n/uk.json @@ -115,7 +115,6 @@ "CenterPanel.Login": "Логін", "CenterPanel.Share": "Поділитися", "ChannelIntro.CreateBoard": "Створити дошку", - "CloudMessage.cloud-server": "Отримайте власний безкоштовний хмарний сервер.", "ColorOption.selectColor": "Виберіть колір {color}", "Comment.delete": "Видалити", "CommentsList.send": "Надіслати", diff --git a/webapp/i18n/zh_Hans.json b/webapp/i18n/zh_Hans.json index 5e176cf61..56dfdd282 100644 --- a/webapp/i18n/zh_Hans.json +++ b/webapp/i18n/zh_Hans.json @@ -115,7 +115,6 @@ "CenterPanel.Login": "登录", "CenterPanel.Share": "分享", "ChannelIntro.CreateBoard": "创建一个板块", - "CloudMessage.cloud-server": "获得自己的免费云服务器。", "ColorOption.selectColor": "选择{color}", "Comment.delete": "删除", "CommentsList.send": "发送", diff --git a/webapp/i18n/zh_Hant.json b/webapp/i18n/zh_Hant.json index 3d7f7f99c..f5438884f 100644 --- a/webapp/i18n/zh_Hant.json +++ b/webapp/i18n/zh_Hant.json @@ -115,7 +115,6 @@ "CenterPanel.Login": "登入", "CenterPanel.Share": "分享", "ChannelIntro.CreateBoard": "建立看板", - "CloudMessage.cloud-server": "獲得免費的雲端伺服器.", "ColorOption.selectColor": "{color} 選擇顏色", "Comment.delete": "刪除", "CommentsList.send": "發送", From 56cc1b84c18f67cdcfc9583e4d924b5c917fd772 Mon Sep 17 00:00:00 2001 From: jprusch Date: Thu, 6 Apr 2023 18:03:55 +0200 Subject: [PATCH 067/102] Translated using Weblate (German) Currently translated at 100.0% (460 of 460 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/de/ Translated using Weblate (German) Currently translated at 100.0% (450 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/de/ --- webapp/i18n/de.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/webapp/i18n/de.json b/webapp/i18n/de.json index c085d2f7c..5a2835d42 100644 --- a/webapp/i18n/de.json +++ b/webapp/i18n/de.json @@ -1,4 +1,6 @@ { + "AdminBadge.SystemAdmin": "Administrator", + "AdminBadge.TeamAdmin": "Teamadministrator", "AppBar.Tooltip": "Verknüpfte Boards umschalten", "Attachment.Attachment-title": "Anhang", "AttachmentBlock.DeleteAction": "Löschen", @@ -22,7 +24,7 @@ "BoardMember.schemeCommenter": "Kommentator", "BoardMember.schemeEditor": "Bearbeiter", "BoardMember.schemeNone": "Keine", - "BoardMember.schemeViewer": "Viewer", + "BoardMember.schemeViewer": "Leser", "BoardMember.unlinkChannel": "Verknüpfung aufheben", "BoardPage.newVersion": "Eine neue Version von Boards ist verfügbar, klicke hier, um neu zu laden.", "BoardPage.syncFailed": "Das Board kann gelöscht oder der Zugang entzogen werden.", @@ -137,6 +139,7 @@ "ContentBlock.moveDown": "Nach unten bewegen", "ContentBlock.moveUp": "Nach oben bewegen", "ContentBlock.text": "Text", + "DateFilter.empty": "Leer", "DateRange.clear": "Leeren", "DateRange.empty": "Leer", "DateRange.endDate": "Enddatum", @@ -155,10 +158,14 @@ "Filter.ends-with": "endet mit", "Filter.includes": "beinhaltet", "Filter.is": "ist", + "Filter.is-after": "ist nach", + "Filter.is-before": "ist vor", "Filter.is-empty": "ist leer", "Filter.is-not-empty": "ist nicht leer", "Filter.is-not-set": "ist nicht gesetzt", "Filter.is-set": "ist gesetzt", + "Filter.isafter": "ist nach", + "Filter.isbefore": "ist vor", "Filter.not-contains": "enthält nicht", "Filter.not-ends-with": "endet nicht mit", "Filter.not-includes": "beinhaltet nicht", @@ -305,6 +312,7 @@ "ValueSelector.valueSelector": "Werteselektor", "ValueSelectorLabel.openMenu": "Menü öffnen", "VersionMessage.help": "Finde raus, was es Neues in dieser Version gibt.", + "VersionMessage.learn-more": "Erfahre mehr", "View.AddView": "Ansicht hinzufügen", "View.Board": "Board", "View.DeleteView": "Ansicht löschen", @@ -359,6 +367,9 @@ "WelcomePage.StartUsingIt.Text": "Verwende es", "Workspace.editing-board-template": "Du bearbeitest eine Board Vorlage.", "badge.guest": "Gast", + "boardPage.confirm-join-button": "Teilnehmen", + "boardPage.confirm-join-text": "Du bist dabei einem privaten Board zu betreten, ohne dass du explizit durch den Board-Administrator hinzugefügt wurdest. Bist du sicher, dass du diesem privaten Board beitreten willst?", + "boardPage.confirm-join-title": "Privatem Board beitreten", "boardSelector.confirm-link-board": "Verknüpfe Board mit Kanal", "boardSelector.confirm-link-board-button": "Ja, verknüpfe Board", "boardSelector.confirm-link-board-subtext": "Wenn du \"{boardName}\" mit diesem Kanal verknüpfst, werden alle Mitglieder des Kanals (aktuelle und neue) das Board bearbeiten können. Dies schließt Mitglieder aus, die Gast sind. Du kannst die Verknüpfung eine Boards mit einem Kanal jederzeit entfernen.", From 4a6cab923345fbafbc4e9aeb704ebdda907ed2c5 Mon Sep 17 00:00:00 2001 From: leonambeez Date: Thu, 6 Apr 2023 18:03:55 +0200 Subject: [PATCH 068/102] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (460 of 460 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/pt_BR/ Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (450 of 450 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/pt_BR/ --- webapp/i18n/pt_BR.json | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/webapp/i18n/pt_BR.json b/webapp/i18n/pt_BR.json index ce693bab5..8b52e1675 100644 --- a/webapp/i18n/pt_BR.json +++ b/webapp/i18n/pt_BR.json @@ -1,5 +1,7 @@ { - "AppBar.Tooltip": "Ativar boards vinculados", + "AdminBadge.SystemAdmin": "Administrador", + "AdminBadge.TeamAdmin": "Administrador de equipe", + "AppBar.Tooltip": "Ativar Boards Vinculados", "Attachment.Attachment-title": "Anexo", "AttachmentBlock.DeleteAction": "excluir", "AttachmentBlock.addElement": "adicionar {type}", @@ -16,7 +18,7 @@ "BoardComponent.hide": "Ocultar", "BoardComponent.new": "Novo", "BoardComponent.no-property": "Sem {property}", - "BoardComponent.no-property-title": "Itens com um {property} vazio estarão aqui. Esta coluna não pode ser removida.", + "BoardComponent.no-property-title": "Itens com um valor {property} vazio aparecerão aqui. Esta coluna não pode ser excluída.", "BoardComponent.show": "Exibir", "BoardMember.schemeAdmin": "Administrador", "BoardMember.schemeCommenter": "Comentarista", @@ -31,7 +33,7 @@ "BoardTemplateSelector.delete-template": "Excluir", "BoardTemplateSelector.description": "Adicione um quadro à barra lateral usando qualquer um dos modelos definidos abaixo ou comece do zero.", "BoardTemplateSelector.edit-template": "Editar", - "BoardTemplateSelector.plugin.no-content-description": "Adicionar um quadro a barra lateral usando qualquer dos templates definidos abaixo ou começar do zero.", + "BoardTemplateSelector.plugin.no-content-description": "Adicione um board à barra lateral usando um dos templates disponíveis abaixo ou comece do zero.", "BoardTemplateSelector.plugin.no-content-title": "Criar um board", "BoardTemplateSelector.title": "Criar um board", "BoardTemplateSelector.use-this-template": "Use este template", @@ -41,16 +43,16 @@ "BoardsUnfurl.Updated": "Atualizado {time}", "Calculations.Options.average.displayName": "Média", "Calculations.Options.average.label": "Média", - "Calculations.Options.count.displayName": "Contagem", - "Calculations.Options.count.label": "Contagem", - "Calculations.Options.countChecked.displayName": "Verificado", - "Calculations.Options.countChecked.label": "Contagem verificada", - "Calculations.Options.countUnchecked.displayName": "Não verificado", - "Calculations.Options.countUnchecked.label": "Contagem não verificada", + "Calculations.Options.count.displayName": "Total", + "Calculations.Options.count.label": "Total", + "Calculations.Options.countChecked.displayName": "Confirmado", + "Calculations.Options.countChecked.label": "Total de itens confirmados", + "Calculations.Options.countUnchecked.displayName": "Não confirmado", + "Calculations.Options.countUnchecked.label": "Total de itens não confirmados", "Calculations.Options.countUniqueValue.displayName": "Único", - "Calculations.Options.countUniqueValue.label": "Contagem valores únicos", + "Calculations.Options.countUniqueValue.label": "Total de valores únicos", "Calculations.Options.countValue.displayName": "Valores", - "Calculations.Options.countValue.label": "Contagem de valor", + "Calculations.Options.countValue.label": "Valor total", "Calculations.Options.dateRange.displayName": "Período", "Calculations.Options.dateRange.label": "Alcance", "Calculations.Options.earliest.displayName": "Mais antigo", @@ -137,6 +139,7 @@ "ContentBlock.moveDown": "Mover para baixo", "ContentBlock.moveUp": "Mover para cima", "ContentBlock.text": "texto", + "DateFilter.empty": "Vazio", "DateRange.clear": "Limpar", "DateRange.empty": "Vazio", "DateRange.endDate": "data de término", @@ -155,10 +158,14 @@ "Filter.ends-with": "termina com", "Filter.includes": "Inclui", "Filter.is": "é", + "Filter.is-after": "está depois", + "Filter.is-before": "está antes", "Filter.is-empty": "está vazio", "Filter.is-not-empty": "Não está vazio", "Filter.is-not-set": "não está definido", "Filter.is-set": "está definido", + "Filter.isafter": "está depois", + "Filter.isbefore": "está antes", "Filter.not-contains": "não contém", "Filter.not-ends-with": "não termina com", "Filter.not-includes": "Não inclui", @@ -305,6 +312,7 @@ "ValueSelector.valueSelector": "Selecionador de valor", "ValueSelectorLabel.openMenu": "Abrir menu", "VersionMessage.help": "Verifique o que é novo nesta versão.", + "VersionMessage.learn-more": "Saiba mais", "View.AddView": "Adicionar visualização", "View.Board": "Quadro", "View.DeleteView": "Excluir visualização", @@ -359,6 +367,9 @@ "WelcomePage.StartUsingIt.Text": "Começar a usar", "Workspace.editing-board-template": "Você está editando um modelo de quadro.", "badge.guest": "Convidado", + "boardPage.confirm-join-button": "Ingressar", + "boardPage.confirm-join-text": "Você está prestes a ingressar em um board privado sem ter sido explicitamente adicionado pelo administrador do quadro. Você tem certeza de que deseja ingressar neste board privado?", + "boardPage.confirm-join-title": "Ingressar board privado", "boardSelector.confirm-link-board": "Linkar board para canal", "boardSelector.confirm-link-board-button": "Sim, linkar board", "boardSelector.confirm-link-board-subtext": "Quando você vincula \"{boardName}\" a um canal, todos os membros daquele canal (existentes e novos) poderão editá-lo. Isto excluirá os membros que são convidados. Você pode desvincular um board de um canal a qualquer hora.", @@ -371,9 +382,10 @@ "calendar.month": "Mês", "calendar.today": "HOJE", "calendar.week": "Semana", + "centerPanel.undefined": "Sem {propertyName}", "centerPanel.unknown-user": "Usuário desconhecido", "cloudMessage.learn-more": "Saiba mais", - "createImageBlock.failed": "Não foi possível enviar o arquivo. Limite de tamanho alcançado.", + "createImageBlock.failed": "Não foi possível enviar o arquivo, pois o tamanho ultrapassou o limite permitido.", "default-properties.badges": "Comentários e descrição", "default-properties.title": "Título", "error.back-to-home": "Volta para o início", @@ -388,7 +400,7 @@ "generic.previous": "Anterior", "guest-no-board.subtitle": "Você não tem acesso a nenhum board neste time ainda, por favor aguarde até alguém adicionar você a algum board.", "guest-no-board.title": "Nenhum board ainda", - "imagePaste.upload-failed": "Alguns arquivos não foram enviados. Tamanho limite alcançado", + "imagePaste.upload-failed": "Alguns arquivos não foram enviados, pois o tamanho ultrapassou o limite permitido.", "limitedCard.title": "Cartões ocultos", "login.log-in-button": "Entrar", "login.log-in-title": "Entrar", @@ -408,6 +420,7 @@ "person.add-user-to-board-confirm-button": "Adicionar ao board", "person.add-user-to-board-permissions": "Permissões", "person.add-user-to-board-question": "Você quer adicionar {username} ao board?", + "person.add-user-to-board-warning": "{username} não é um membro do quadro e não receberá nenhuma notificação sobre ele.", "register.login-button": "ou entre se você já tem uma conta", "register.signup-title": "Registrar uma conta", "rhs-board-non-admin-msg": "Você não é um adminstrador do quadro", From 77b8a8e14d6cf9bf4dc5980de8d6401eb27d17b0 Mon Sep 17 00:00:00 2001 From: master7 Date: Thu, 6 Apr 2023 18:03:56 +0200 Subject: [PATCH 069/102] Translated using Weblate (Polish) Currently translated at 100.0% (460 of 460 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/pl/ --- webapp/i18n/pl.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/webapp/i18n/pl.json b/webapp/i18n/pl.json index 903d7112e..893ec7016 100644 --- a/webapp/i18n/pl.json +++ b/webapp/i18n/pl.json @@ -1,5 +1,7 @@ { - "AppBar.Tooltip": "Przełączanie podlinkowanych tablic", + "AdminBadge.SystemAdmin": "Administrator", + "AdminBadge.TeamAdmin": "Administrator Zespołu", + "AppBar.Tooltip": "Przełączanie Podlinkowanych Tablic", "Attachment.Attachment-title": "Załącznik", "AttachmentBlock.DeleteAction": "usuń", "AttachmentBlock.addElement": "dodaj {type}", @@ -137,6 +139,7 @@ "ContentBlock.moveDown": "Przenieś w dół", "ContentBlock.moveUp": "Przenieś w górę", "ContentBlock.text": "tekst", + "DateFilter.empty": "Puste", "DateRange.clear": "Wyczyść", "DateRange.empty": "Puste", "DateRange.endDate": "Data końcowa", @@ -155,10 +158,14 @@ "Filter.ends-with": "kończy się na", "Filter.includes": "zawiera", "Filter.is": "jest", + "Filter.is-after": "jest po", + "Filter.is-before": "jest przed", "Filter.is-empty": "jest pusty", "Filter.is-not-empty": "nie jest pusty", "Filter.is-not-set": "nie jest ustawiony", "Filter.is-set": "jest ustawiony", + "Filter.isafter": "jest po", + "Filter.isbefore": "jest przed", "Filter.not-contains": "nie zawiera", "Filter.not-ends-with": "nie kończy się na", "Filter.not-includes": "nie zawiera", @@ -305,6 +312,7 @@ "ValueSelector.valueSelector": "Selektor wartości", "ValueSelectorLabel.openMenu": "Otwórz menu", "VersionMessage.help": "Sprawdź co nowego w tej wersji.", + "VersionMessage.learn-more": "Dowiedź się więcej", "View.AddView": "Dodaj widok", "View.Board": "Tablica", "View.DeleteView": "Usuń widok", @@ -359,6 +367,9 @@ "WelcomePage.StartUsingIt.Text": "Zacznij używać", "Workspace.editing-board-template": "Edytujesz szablon tablicy.", "badge.guest": "Gość", + "boardPage.confirm-join-button": "Dołącz", + "boardPage.confirm-join-text": "Zamierzasz dołączyć do prywatnej tablicy bez wyraźnego dodania przez administratora forum. Czy na pewno chcesz dołączyć do tego prywatnego forum?", + "boardPage.confirm-join-title": "Dołącz do prywatnej tablicy", "boardSelector.confirm-link-board": "Połączenie tablicy z kanałem", "boardSelector.confirm-link-board-button": "Tak, podlinkuj tablicę", "boardSelector.confirm-link-board-subtext": "Kiedy połączysz \"{boardName}\" z kanałem, wszyscy członkowie kanału (istniejący i nowi) będą mogli go edytować. Nie dotyczy to członków, którzy są gośćmi. W każdej chwili możesz odłączyć tablicę od kanału.", From 1381babf37e1fbb5858f3c9437646a46a1c3d88d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20Balsevi=C4=8Dius?= Date: Thu, 6 Apr 2023 18:03:56 +0200 Subject: [PATCH 070/102] Added translation using Weblate (Lithuanian) --- webapp/i18n/lt.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 webapp/i18n/lt.json diff --git a/webapp/i18n/lt.json b/webapp/i18n/lt.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/webapp/i18n/lt.json @@ -0,0 +1 @@ +{} From 236099f40e8e2db3c18a3a699dbd31ad4f7dcf6c Mon Sep 17 00:00:00 2001 From: Kaya Zeren Date: Thu, 6 Apr 2023 18:03:56 +0200 Subject: [PATCH 071/102] Translated using Weblate (Turkish) Currently translated at 100.0% (460 of 460 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/tr/ --- webapp/i18n/tr.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/webapp/i18n/tr.json b/webapp/i18n/tr.json index 3c071a3f6..0c9614a80 100644 --- a/webapp/i18n/tr.json +++ b/webapp/i18n/tr.json @@ -1,4 +1,6 @@ { + "AdminBadge.SystemAdmin": "Yönetici", + "AdminBadge.TeamAdmin": "Takım yöneticisi", "AppBar.Tooltip": "Bağlantılı panoları aç/kapat", "Attachment.Attachment-title": "Ek dosya", "AttachmentBlock.DeleteAction": "sil", @@ -137,6 +139,7 @@ "ContentBlock.moveDown": "Alta taşı", "ContentBlock.moveUp": "Üste taşı", "ContentBlock.text": "metin", + "DateFilter.empty": "Boş", "DateRange.clear": "Temizle", "DateRange.empty": "Boş", "DateRange.endDate": "Bitiş tarihi", @@ -155,10 +158,14 @@ "Filter.ends-with": "şununla biten", "Filter.includes": "şunu içeren", "Filter.is": "şu olan", + "Filter.is-after": "şundan sonra", + "Filter.is-before": "şundan önce", "Filter.is-empty": "boş olan", "Filter.is-not-empty": "boş olmayan", "Filter.is-not-set": "şuna ayarlanmamış olan", "Filter.is-set": "şuna ayarlanmış olan", + "Filter.isafter": "şundan sonra", + "Filter.isbefore": "şundan önce", "Filter.not-contains": "şunu içermeyen", "Filter.not-ends-with": "şununla bitmeyen", "Filter.not-includes": "şunu içermeyen", @@ -305,6 +312,7 @@ "ValueSelector.valueSelector": "Değer seçici", "ValueSelectorLabel.openMenu": "Menüyü aç", "VersionMessage.help": "Bu sürümdeki yeniliklere bakın.", + "VersionMessage.learn-more": "Ayrıntılı bilgi alın", "View.AddView": "Görünüm ekle", "View.Board": "Pano", "View.DeleteView": "Görünümü sil", @@ -359,6 +367,9 @@ "WelcomePage.StartUsingIt.Text": "Kullanmaya başlayın", "Workspace.editing-board-template": "Bir pano kalıbını düzenliyorsunuz.", "badge.guest": "Konuk", + "boardPage.confirm-join-button": "Katıl", + "boardPage.confirm-join-text": "Bir özel kanala, pano yöneticisi tarafından açıkça eklenmeden katılmak üzeresiniz. Bu özel kanala katılmak istediğinize emin misiniz?", + "boardPage.confirm-join-title": "Özel kanala katıl", "boardSelector.confirm-link-board": "Panoyu kanala bağla", "boardSelector.confirm-link-board-button": "Evet, panoyu bağla", "boardSelector.confirm-link-board-subtext": "\"{boardName}\" panosunu kanala bağladığınızda, kanalın tüm üyeleri (var olan ve yeni) panoyu düzenleyebilir. Bu işlem konuk üyeleri kaldırır. Bir pano ile bir kanalın bağlantısını istediğiniz zaman kaldırabilirsiniz.", From 1388d41a9bb20ef253cb99ea67a321890c3fc3f7 Mon Sep 17 00:00:00 2001 From: Matthew Williams Date: Thu, 6 Apr 2023 18:03:56 +0200 Subject: [PATCH 072/102] Translated using Weblate (English (Australia)) Currently translated at 100.0% (460 of 460 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/en_AU/ --- webapp/i18n/en_AU.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/webapp/i18n/en_AU.json b/webapp/i18n/en_AU.json index 8165346f7..a998a55e6 100644 --- a/webapp/i18n/en_AU.json +++ b/webapp/i18n/en_AU.json @@ -1,5 +1,7 @@ { - "AppBar.Tooltip": "Toggle linked boards", + "AdminBadge.SystemAdmin": "Admin", + "AdminBadge.TeamAdmin": "Team Admin", + "AppBar.Tooltip": "Toggle Linked Boards", "Attachment.Attachment-title": "Attachment", "AttachmentBlock.DeleteAction": "delete", "AttachmentBlock.addElement": "add {type}", @@ -137,6 +139,7 @@ "ContentBlock.moveDown": "Move down", "ContentBlock.moveUp": "Move up", "ContentBlock.text": "text", + "DateFilter.empty": "Empty", "DateRange.clear": "Clear", "DateRange.empty": "Empty", "DateRange.endDate": "End date", @@ -155,10 +158,14 @@ "Filter.ends-with": "ends with", "Filter.includes": "includes", "Filter.is": "is", + "Filter.is-after": "is after", + "Filter.is-before": "is before", "Filter.is-empty": "is empty", "Filter.is-not-empty": "is not empty", "Filter.is-not-set": "is not set", "Filter.is-set": "is set", + "Filter.isafter": "is after", + "Filter.isbefore": "is before", "Filter.not-contains": "does not contain", "Filter.not-ends-with": "does not end with", "Filter.not-includes": "doesn't include", @@ -305,6 +312,7 @@ "ValueSelector.valueSelector": "Value selector", "ValueSelectorLabel.openMenu": "Open menu", "VersionMessage.help": "Check out what's new in this version.", + "VersionMessage.learn-more": "Learn more", "View.AddView": "Add view", "View.Board": "Board", "View.DeleteView": "Delete view", @@ -359,6 +367,9 @@ "WelcomePage.StartUsingIt.Text": "Start using it", "Workspace.editing-board-template": "You're editing a board template.", "badge.guest": "Guest", + "boardPage.confirm-join-button": "Join", + "boardPage.confirm-join-text": "You are about to join a private board without explicitly being added by the board admin. Are you sure you wish to join this private board?", + "boardPage.confirm-join-title": "Join private board", "boardSelector.confirm-link-board": "Link board to channel", "boardSelector.confirm-link-board-button": "Link board", "boardSelector.confirm-link-board-subtext": "When you link '\\{boardName}'\\ to the channel, all members of the channel (existing and new) will be able to edit it. This excludes members who are guests. You can unlink a board from a channel at any time.", From 4e7416358ee0d787fd9ef4e7fd1c961de1f95895 Mon Sep 17 00:00:00 2001 From: Milo Ivir Date: Thu, 6 Apr 2023 18:03:57 +0200 Subject: [PATCH 073/102] Translated using Weblate (Croatian) Currently translated at 100.0% (460 of 460 strings) Translation: Focalboard/webapp Translate-URL: https://translate.mattermost.com/projects/focalboard/webapp/hr/ --- webapp/i18n/hr.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/webapp/i18n/hr.json b/webapp/i18n/hr.json index 24236441c..23f7f3579 100644 --- a/webapp/i18n/hr.json +++ b/webapp/i18n/hr.json @@ -1,4 +1,6 @@ { + "AdminBadge.SystemAdmin": "Administrator", + "AdminBadge.TeamAdmin": "Tim administratora", "AppBar.Tooltip": "Uklj./Isklj. povezane ploče", "Attachment.Attachment-title": "Prilog", "AttachmentBlock.DeleteAction": "izbriši", @@ -137,6 +139,7 @@ "ContentBlock.moveDown": "Pomakni dolje", "ContentBlock.moveUp": "Pomakni gore", "ContentBlock.text": "tekst", + "DateFilter.empty": "Prazno", "DateRange.clear": "Isprazni", "DateRange.empty": "Prazno", "DateRange.endDate": "Datum kraja", @@ -155,10 +158,14 @@ "Filter.ends-with": "završava sa", "Filter.includes": "uključuje", "Filter.is": "je", + "Filter.is-after": "je nakon", + "Filter.is-before": "je prije", "Filter.is-empty": "je prazno", "Filter.is-not-empty": "nije prazno", "Filter.is-not-set": "nije postavljeno", "Filter.is-set": "je postavljeno", + "Filter.isafter": "je nakon", + "Filter.isbefore": "je prije", "Filter.not-contains": "ne sadrži", "Filter.not-ends-with": "ne završava sa", "Filter.not-includes": "ne uključuje", @@ -305,6 +312,7 @@ "ValueSelector.valueSelector": "Selektor vrijednosti", "ValueSelectorLabel.openMenu": "Otvori izbornik", "VersionMessage.help": "Provjeri što je novo u ovoj verziji.", + "VersionMessage.learn-more": "Saznaj više", "View.AddView": "Dodaj prikaz", "View.Board": "Ploča", "View.DeleteView": "Izbriši prikaz", @@ -359,6 +367,9 @@ "WelcomePage.StartUsingIt.Text": "Počni ga koristiti", "Workspace.editing-board-template": "Uređuješ predložak ploče.", "badge.guest": "Gost", + "boardPage.confirm-join-button": "Pridruži se", + "boardPage.confirm-join-text": "Pridružit ćeš se privatnoj ploči bez da te je administrator ploče izričito dodao. Stvarno se želiš pridružiti ovoj privatnoj ploči?", + "boardPage.confirm-join-title": "Pridruži se privatnoj ploči", "boardSelector.confirm-link-board": "Poveži ploču s kanalom", "boardSelector.confirm-link-board-button": "Da, poveži ploču", "boardSelector.confirm-link-board-subtext": "Kad povežeš ploču „{boardName}” s kanalom, svi članovi kanala (postojeći i novi) moći će je uređivati. To ne vrijedi za članove koji su gosti. Vezu između ploče i kanala možeš raskinuti u bilo kojem trenutku.", From 8cf0ec3a61fc5f11a646b97967698ea457c619c8 Mon Sep 17 00:00:00 2001 From: Eric Sethna Date: Wed, 5 Jul 2023 07:39:26 -0700 Subject: [PATCH 074/102] Update README.md (#4794) --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index fa837cb4a..9ec4739f2 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,6 @@ # :warning: Announcement: PLEASE READ :warning: Focalboard Personal Server and Personal Desktop editions will transition to being fully community supported as of **April 30th, 2023**. This Focalboard repository will become the Personal Edition repository, and will remain open indefinitely. However, we won’t be adding any new enhancements, and will only address Sev-1 level bugs until April 30th, 2023. -The Boards plugin version will be integrated into Mattermost as a core in-product feature, and will no longer be supported as a plugin as of release v7.11 (May 2023). The plugin code will be merged into the [Mattermost-server repository](https://github.com/mattermost/mattermost-server) where future enhancements will be added to moving forward. New pull requests and issues should be filed against https://github.com/mattermost/mattermost-server. - -Please see [this dicussion](https://github.com/mattermost/focalboard/discussions/4645) for more details. - # Focalboard ![CI Status](https://github.com/mattermost/focalboard/actions/workflows/ci.yml/badge.svg) From a745c29cb1dbe8acb7b6cb851cac879c7d3031e3 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Mon, 10 Jul 2023 09:46:55 -0600 Subject: [PATCH 075/102] update version to v7.11.1 (#4797) --- mattermost-plugin/plugin.json | 2 +- mattermost-plugin/server/manifest.go | 2 +- server/model/version.go | 1 + webapp/package-lock.json | 4 ++-- webapp/package.json | 2 +- .../__snapshots__/globalHeader.test.tsx.snap | 2 +- .../__snapshots__/sidebar.test.tsx.snap | 20 +++++++++---------- webapp/src/constants.ts | 2 +- 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/mattermost-plugin/plugin.json b/mattermost-plugin/plugin.json index 968d898c6..b8e5d3cbe 100644 --- a/mattermost-plugin/plugin.json +++ b/mattermost-plugin/plugin.json @@ -6,7 +6,7 @@ "support_url": "https://github.com/mattermost/focalboard/issues", "release_notes_url": "https://github.com/mattermost/focalboard/releases", "icon_path": "assets/starter-template-icon.svg", - "version": "7.11.0", + "version": "7.11.1", "min_server_version": "7.2.0", "server": { "executables": { diff --git a/mattermost-plugin/server/manifest.go b/mattermost-plugin/server/manifest.go index ea3af5430..7446c699a 100644 --- a/mattermost-plugin/server/manifest.go +++ b/mattermost-plugin/server/manifest.go @@ -20,7 +20,7 @@ const manifestStr = ` "support_url": "https://github.com/mattermost/focalboard/issues", "release_notes_url": "https://github.com/mattermost/focalboard/releases", "icon_path": "assets/starter-template-icon.svg", - "version": "7.11.0", + "version": "7.11.1", "min_server_version": "7.2.0", "server": { "executables": { diff --git a/server/model/version.go b/server/model/version.go index 932daf832..79baf0a15 100644 --- a/server/model/version.go +++ b/server/model/version.go @@ -8,6 +8,7 @@ import ( // It should be maintained in chronological order with most current // release at the front of the list. var versions = []string{ + "7.11.1", "7.11.0", "7.10.0", "7.9.0", diff --git a/webapp/package-lock.json b/webapp/package-lock.json index e122f1ab5..659ba71f1 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -1,12 +1,12 @@ { "name": "focalboard", - "version": "7.11.0", + "version": "7.11.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "focalboard", - "version": "7.11.0", + "version": "7.11.1", "dependencies": { "@draft-js-plugins/editor": "^4.1.2", "@draft-js-plugins/emoji": "^4.6.0", diff --git a/webapp/package.json b/webapp/package.json index f3729cd98..ba0c7a68b 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -1,6 +1,6 @@ { "name": "focalboard", - "version": "7.11.0", + "version": "7.11.1", "private": true, "description": "", "scripts": { diff --git a/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap b/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap index 69dbc4f9d..657cc1a34 100644 --- a/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap +++ b/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap @@ -10,7 +10,7 @@ exports[`components/sidebar/GlobalHeader header menu should match snapshot 1`] = />
diff --git a/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap b/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap index 0320ed43c..fc9d699c6 100644 --- a/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap +++ b/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap @@ -51,9 +51,9 @@ exports[`components/sidebarSidebar dont show hidden boards 1`] = ` >
- v7.11.0 + v7.11.1
@@ -252,9 +252,9 @@ exports[`components/sidebarSidebar should assign default category if current boa >
- v7.11.0 + v7.11.1
@@ -508,9 +508,9 @@ exports[`components/sidebarSidebar shouldnt do any category assignment is board >
- v7.11.0 + v7.11.1
@@ -919,9 +919,9 @@ exports[`components/sidebarSidebar sidebar hidden 1`] = ` >
- v7.11.0 + v7.11.1
@@ -1213,9 +1213,9 @@ exports[`components/sidebarSidebar some categories hidden 1`] = ` >
- v7.11.0 + v7.11.1
diff --git a/webapp/src/constants.ts b/webapp/src/constants.ts index e5e1f4cea..17c59ad8f 100644 --- a/webapp/src/constants.ts +++ b/webapp/src/constants.ts @@ -37,7 +37,7 @@ class Constants { static readonly titleColumnId = '__title' static readonly badgesColumnId = '__badges' - static readonly versionString = '7.11.0' + static readonly versionString = '7.11.1' static readonly versionDisplayString = 'May 2023' static readonly archiveHelpPage = 'https://docs.mattermost.com/boards/migrate-to-boards.html' From e0dbb380a35aa48f2cd7ab160d8bb8339430d5af Mon Sep 17 00:00:00 2001 From: Miguel de la Cruz Date: Thu, 20 Jul 2023 09:50:25 +0200 Subject: [PATCH 076/102] Adds the parent ID filter when fetching child blocks to extract fileId and attachmentId (#4802) --- server/services/store/sqlstore/blocks.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/services/store/sqlstore/blocks.go b/server/services/store/sqlstore/blocks.go index a22daddb7..c06412c0f 100644 --- a/server/services/store/sqlstore/blocks.go +++ b/server/services/store/sqlstore/blocks.go @@ -956,6 +956,10 @@ func (s *SQLStore) deleteBlockChildren(db sq.BaseRunner, boardID string, parentI From(s.tablePrefix + "blocks"). Where(sq.Eq{"board_id": boardID}) + if parentID != "" { + fileDeleteQuery = fileDeleteQuery.Where(sq.Eq{"parent_id": parentID}) + } + rows, err := fileDeleteQuery.Query() if err != nil { return err From 9901557d99c693c8ed54aa9bd2faf8a08a656ada Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Fri, 21 Jul 2023 02:27:13 -0600 Subject: [PATCH 077/102] update minimum dependencies (#4811) * update minimum dependencies * update minimum dependencies --- linux/go.mod | 6 +++--- linux/go.sum | 12 ++++++------ mattermost-plugin/go.mod | 6 +++--- mattermost-plugin/go.sum | 12 ++++++------ server/go.mod | 6 +++--- server/go.sum | 12 ++++++------ 6 files changed, 27 insertions(+), 27 deletions(-) diff --git a/linux/go.mod b/linux/go.mod index 43d5ea479..aa6733fb7 100644 --- a/linux/go.mod +++ b/linux/go.mod @@ -97,10 +97,10 @@ require ( github.com/yuin/goldmark v1.5.3 // indirect golang.org/x/crypto v0.5.0 // indirect golang.org/x/mod v0.7.0 // indirect - golang.org/x/net v0.5.0 // indirect + golang.org/x/net v0.7.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.4.0 // indirect - golang.org/x/text v0.6.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect golang.org/x/tools v0.5.0 // indirect google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf // indirect google.golang.org/grpc v1.51.0 // indirect diff --git a/linux/go.sum b/linux/go.sum index 68ebfbdb7..8a16c526f 100644 --- a/linux/go.sum +++ b/linux/go.sum @@ -1506,8 +1506,8 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1679,8 +1679,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1697,8 +1697,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/mattermost-plugin/go.mod b/mattermost-plugin/go.mod index a1076a211..87ff73af5 100644 --- a/mattermost-plugin/go.mod +++ b/mattermost-plugin/go.mod @@ -97,10 +97,10 @@ require ( github.com/yuin/goldmark v1.5.3 // indirect golang.org/x/crypto v0.5.0 // indirect golang.org/x/mod v0.7.0 // indirect - golang.org/x/net v0.5.0 // indirect + golang.org/x/net v0.7.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.4.0 // indirect - golang.org/x/text v0.6.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect golang.org/x/tools v0.5.0 // indirect google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf // indirect google.golang.org/grpc v1.51.0 // indirect diff --git a/mattermost-plugin/go.sum b/mattermost-plugin/go.sum index 47dbae4bb..168f8e7d8 100644 --- a/mattermost-plugin/go.sum +++ b/mattermost-plugin/go.sum @@ -1507,8 +1507,8 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1680,8 +1680,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1698,8 +1698,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/server/go.mod b/server/go.mod index 6f548eed7..421c8f126 100644 --- a/server/go.mod +++ b/server/go.mod @@ -96,10 +96,10 @@ require ( github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect github.com/yuin/goldmark v1.5.3 // indirect golang.org/x/mod v0.7.0 // indirect - golang.org/x/net v0.5.0 // indirect + golang.org/x/net v0.7.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.4.0 // indirect - golang.org/x/text v0.6.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect golang.org/x/tools v0.5.0 // indirect google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf // indirect google.golang.org/grpc v1.51.0 // indirect diff --git a/server/go.sum b/server/go.sum index 7f06fadff..240811f78 100644 --- a/server/go.sum +++ b/server/go.sum @@ -1508,8 +1508,8 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1681,8 +1681,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1699,8 +1699,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From e6b67af8b182ab7cd14ffafc327e74c63eaaf390 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Fri, 21 Jul 2023 10:57:10 -0600 Subject: [PATCH 078/102] update version v7.12.0 (#4814) --- mattermost-plugin/plugin.json | 2 +- mattermost-plugin/server/manifest.go | 2 +- server/model/version.go | 1 + webapp/package-lock.json | 4 ++-- webapp/package.json | 2 +- .../__snapshots__/globalHeader.test.tsx.snap | 2 +- .../__snapshots__/sidebar.test.tsx.snap | 20 +++++++++---------- webapp/src/constants.ts | 2 +- 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/mattermost-plugin/plugin.json b/mattermost-plugin/plugin.json index b8e5d3cbe..2b86d0fc7 100644 --- a/mattermost-plugin/plugin.json +++ b/mattermost-plugin/plugin.json @@ -6,7 +6,7 @@ "support_url": "https://github.com/mattermost/focalboard/issues", "release_notes_url": "https://github.com/mattermost/focalboard/releases", "icon_path": "assets/starter-template-icon.svg", - "version": "7.11.1", + "version": "7.12.0", "min_server_version": "7.2.0", "server": { "executables": { diff --git a/mattermost-plugin/server/manifest.go b/mattermost-plugin/server/manifest.go index 7446c699a..f66d9e73f 100644 --- a/mattermost-plugin/server/manifest.go +++ b/mattermost-plugin/server/manifest.go @@ -20,7 +20,7 @@ const manifestStr = ` "support_url": "https://github.com/mattermost/focalboard/issues", "release_notes_url": "https://github.com/mattermost/focalboard/releases", "icon_path": "assets/starter-template-icon.svg", - "version": "7.11.1", + "version": "7.12.0", "min_server_version": "7.2.0", "server": { "executables": { diff --git a/server/model/version.go b/server/model/version.go index 79baf0a15..bbfd8393e 100644 --- a/server/model/version.go +++ b/server/model/version.go @@ -8,6 +8,7 @@ import ( // It should be maintained in chronological order with most current // release at the front of the list. var versions = []string{ + "7.12.0", "7.11.1", "7.11.0", "7.10.0", diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 659ba71f1..d5acbb97e 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -1,12 +1,12 @@ { "name": "focalboard", - "version": "7.11.1", + "version": "7.12.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "focalboard", - "version": "7.11.1", + "version": "7.12.0", "dependencies": { "@draft-js-plugins/editor": "^4.1.2", "@draft-js-plugins/emoji": "^4.6.0", diff --git a/webapp/package.json b/webapp/package.json index ba0c7a68b..b15469a7b 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -1,6 +1,6 @@ { "name": "focalboard", - "version": "7.11.1", + "version": "7.12.0", "private": true, "description": "", "scripts": { diff --git a/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap b/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap index 657cc1a34..46c6d324a 100644 --- a/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap +++ b/webapp/src/components/globalHeader/__snapshots__/globalHeader.test.tsx.snap @@ -10,7 +10,7 @@ exports[`components/sidebar/GlobalHeader header menu should match snapshot 1`] = />
diff --git a/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap b/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap index fc9d699c6..fea848106 100644 --- a/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap +++ b/webapp/src/components/sidebar/__snapshots__/sidebar.test.tsx.snap @@ -51,9 +51,9 @@ exports[`components/sidebarSidebar dont show hidden boards 1`] = ` >
- v7.11.1 + v7.12.0
@@ -252,9 +252,9 @@ exports[`components/sidebarSidebar should assign default category if current boa >
- v7.11.1 + v7.12.0
@@ -508,9 +508,9 @@ exports[`components/sidebarSidebar shouldnt do any category assignment is board >
- v7.11.1 + v7.12.0
@@ -919,9 +919,9 @@ exports[`components/sidebarSidebar sidebar hidden 1`] = ` >
- v7.11.1 + v7.12.0
@@ -1213,9 +1213,9 @@ exports[`components/sidebarSidebar some categories hidden 1`] = ` >
- v7.11.1 + v7.12.0
diff --git a/webapp/src/constants.ts b/webapp/src/constants.ts index 17c59ad8f..9f8504723 100644 --- a/webapp/src/constants.ts +++ b/webapp/src/constants.ts @@ -37,7 +37,7 @@ class Constants { static readonly titleColumnId = '__title' static readonly badgesColumnId = '__badges' - static readonly versionString = '7.11.1' + static readonly versionString = '7.12.0' static readonly versionDisplayString = 'May 2023' static readonly archiveHelpPage = 'https://docs.mattermost.com/boards/migrate-to-boards.html' From 257cc5f1fd167cc791dd482a30b872da9743bff2 Mon Sep 17 00:00:00 2001 From: Miguel de la Cruz Date: Fri, 21 Jul 2023 19:42:29 +0200 Subject: [PATCH 079/102] Adds a database migration to restore the fileinfos that are deleted (#4815) --- .../000040_fix_fileinfo_soft_deletes.down.sql | 1 + .../000040_fix_fileinfo_soft_deletes.up.sql | 8 ++++ .../fixtures/test40FixFileinfoSoftDeletes.sql | 9 ++++ .../migrationstests/migration40_test.go | 48 +++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 server/services/store/sqlstore/migrations/000040_fix_fileinfo_soft_deletes.down.sql create mode 100644 server/services/store/sqlstore/migrations/000040_fix_fileinfo_soft_deletes.up.sql create mode 100644 server/services/store/sqlstore/migrationstests/fixtures/test40FixFileinfoSoftDeletes.sql create mode 100644 server/services/store/sqlstore/migrationstests/migration40_test.go diff --git a/server/services/store/sqlstore/migrations/000040_fix_fileinfo_soft_deletes.down.sql b/server/services/store/sqlstore/migrations/000040_fix_fileinfo_soft_deletes.down.sql new file mode 100644 index 000000000..e0ac49d1e --- /dev/null +++ b/server/services/store/sqlstore/migrations/000040_fix_fileinfo_soft_deletes.down.sql @@ -0,0 +1 @@ +SELECT 1; diff --git a/server/services/store/sqlstore/migrations/000040_fix_fileinfo_soft_deletes.up.sql b/server/services/store/sqlstore/migrations/000040_fix_fileinfo_soft_deletes.up.sql new file mode 100644 index 000000000..156ca4edc --- /dev/null +++ b/server/services/store/sqlstore/migrations/000040_fix_fileinfo_soft_deletes.up.sql @@ -0,0 +1,8 @@ +{{if .plugin}} + UPDATE FileInfo + SET DeleteAt = 0 + WHERE CreatorId = 'boards' + AND DeleteAt != 0; +{{else}} +SELECT 1; +{{end}} diff --git a/server/services/store/sqlstore/migrationstests/fixtures/test40FixFileinfoSoftDeletes.sql b/server/services/store/sqlstore/migrationstests/fixtures/test40FixFileinfoSoftDeletes.sql new file mode 100644 index 000000000..6abc8f145 --- /dev/null +++ b/server/services/store/sqlstore/migrationstests/fixtures/test40FixFileinfoSoftDeletes.sql @@ -0,0 +1,9 @@ +INSERT INTO FileInfo +(Id, CreatorId, CreateAt, UpdateAt, DeleteAt) +VALUES +('fileinfo-1', 'user-id', 1, 1, 1000), +('fileinfo-2', 'user-id', 1, 1, 1000), +('fileinfo-3', 'user-id', 1, 1, 0), +('fileinfo-4', 'boards', 1, 1, 2000), +('fileinfo-5', 'boards', 1, 1, 2000), +('fileinfo-6', 'boards', 1, 1, 0); diff --git a/server/services/store/sqlstore/migrationstests/migration40_test.go b/server/services/store/sqlstore/migrationstests/migration40_test.go new file mode 100644 index 000000000..66ce1faea --- /dev/null +++ b/server/services/store/sqlstore/migrationstests/migration40_test.go @@ -0,0 +1,48 @@ +package migrationstests + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func Test40FixFileinfoSoftDeletes(t *testing.T) { + th, tearDown := SetupPluginTestHelper(t) + defer tearDown() + + th.f.MigrateToStep(39). + ExecFile("./fixtures/test40FixFileinfoSoftDeletes.sql"). + MigrateToStep(40) + + type FileInfo struct { + Id string + DeleteAt int + } + + getFileInfo := func(t *testing.T, id string) FileInfo { + t.Helper() + fileInfo := FileInfo{} + + query := "SELECT id, deleteat FROM FileInfo WHERE id = $1" + if th.IsMySQL() { + query = "SELECT Id as id, DeleteAt as deleteat FROM FileInfo WHERE Id = ?" + } + + err := th.f.DB().Get(&fileInfo, query, id) + require.NoError(t, err) + + return fileInfo + } + + t.Run("the file infos that don't belong to boards will not be restored", func(t *testing.T) { + require.Equal(t, 1000, getFileInfo(t, "fileinfo-1").DeleteAt) + require.Equal(t, 1000, getFileInfo(t, "fileinfo-2").DeleteAt) + require.Empty(t, getFileInfo(t, "fileinfo-3").DeleteAt) + }) + + t.Run("the file infos that belong to boards should correctly be restored", func(t *testing.T) { + require.Empty(t, getFileInfo(t, "fileinfo-3").DeleteAt) + require.Empty(t, getFileInfo(t, "fileinfo-4").DeleteAt) + require.Empty(t, getFileInfo(t, "fileinfo-5").DeleteAt) + }) +} From 3625c535275378e46b0cc4dcf19295cd6d2a275b Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Wed, 26 Jul 2023 08:42:22 -0400 Subject: [PATCH 080/102] Sanitize user following config for ShowFullName and ShowEmailAddress (#4820) --- server/api/users.go | 19 +++++++++++++++++++ server/app/user.go | 12 ++++++++++++ server/model/user.go | 13 +++++++++++++ .../mattermostauthlayer.go | 1 + .../mattermostauthlayer_test.go | 1 - 5 files changed, 45 insertions(+), 1 deletion(-) diff --git a/server/api/users.go b/server/api/users.go index 4d88e41bc..8310ed5b5 100644 --- a/server/api/users.go +++ b/server/api/users.go @@ -89,6 +89,18 @@ func (a *API) handleGetUsersList(w http.ResponseWriter, r *http.Request) { } } + ctx := r.Context() + session := ctx.Value(sessionContextKey).(*model.Session) + isSystemAdmin := a.permissions.HasPermissionTo(session.UserID, model.PermissionManageSystem) + + for _, user := range users { + if user.ID == session.UserID { + user.Sanitize(map[string]bool{}) + } else { + a.app.SanitizeProfile(user, isSystemAdmin) + } + } + usersList, err := json.Marshal(users) if err != nil { a.errorResponse(w, r, err) @@ -170,6 +182,7 @@ func (a *API) handleGetMe(w http.ResponseWriter, r *http.Request) { user.Permissions = append(user.Permissions, model.PermissionCreatePost.Id) } + user.Sanitize(map[string]bool{}) userData, err := json.Marshal(user) if err != nil { a.errorResponse(w, r, err) @@ -278,6 +291,12 @@ func (a *API) handleGetUser(w http.ResponseWriter, r *http.Request) { return } + if userID == session.UserID { + user.Sanitize(map[string]bool{}) + } else { + a.app.SanitizeProfile(user, a.permissions.HasPermissionTo(session.UserID, model.PermissionManageSystem)) + } + userData, err := json.Marshal(user) if err != nil { a.errorResponse(w, r, err) diff --git a/server/app/user.go b/server/app/user.go index bfddca40c..92f3f5b87 100644 --- a/server/app/user.go +++ b/server/app/user.go @@ -80,3 +80,15 @@ func (a *App) SearchUserChannels(teamID string, userID string, query string) ([] func (a *App) GetChannel(teamID string, channelID string) (*mmModel.Channel, error) { return a.store.GetChannel(teamID, channelID) } + +func (a *App) SanitizeProfile(user *model.User, isAdmin bool) { + options := map[string]bool{} + if isAdmin { + options["fullname"] = true + options["email"] = true + } else { + options["fullname"] = a.config.ShowFullName + options["email"] = a.config.ShowEmailAddress + } + user.Sanitize(options) +} diff --git a/server/model/user.go b/server/model/user.go index 37c1f946d..1840e082f 100644 --- a/server/model/user.go +++ b/server/model/user.go @@ -101,3 +101,16 @@ func UserFromJSON(data io.Reader) (*User, error) { } return &user, nil } + +func (u *User) Sanitize(options map[string]bool) { + u.Password = "" + u.MfaSecret = "" + + if len(options) != 0 && !options["email"] { + u.Email = "" + } + if len(options) != 0 && !options["fullname"] { + u.FirstName = "" + u.LastName = "" + } +} diff --git a/server/services/store/mattermostauthlayer/mattermostauthlayer.go b/server/services/store/mattermostauthlayer/mattermostauthlayer.go index 2696b382c..01a80aeda 100644 --- a/server/services/store/mattermostauthlayer/mattermostauthlayer.go +++ b/server/services/store/mattermostauthlayer/mattermostauthlayer.go @@ -93,6 +93,7 @@ func (s *MattermostAuthLayer) GetUserByID(userID string) (*model.User, error) { if err != nil { return nil, err } + user := mmUserToFbUser(mmuser) return &user, nil } diff --git a/server/services/store/mattermostauthlayer/mattermostauthlayer_test.go b/server/services/store/mattermostauthlayer/mattermostauthlayer_test.go index 3db253f90..b1a340913 100644 --- a/server/services/store/mattermostauthlayer/mattermostauthlayer_test.go +++ b/server/services/store/mattermostauthlayer/mattermostauthlayer_test.go @@ -18,7 +18,6 @@ var errTest = errors.New("failed to patch bot") func TestGetBoardsBotID(t *testing.T) { ctrl := gomock.NewController(t) servicesAPI := mockservicesapi.NewMockServicesAPI(ctrl) - mmAuthLayer, _ := New("test", nil, nil, mlog.CreateConsoleTestLogger(true, mlog.LvlError), servicesAPI, "") servicesAPI.EXPECT().EnsureBot(model.FocalboardBot).Return("", errTest) From dd3be3e3ed1cfebd46f6cac9e74a82083ff94c46 Mon Sep 17 00:00:00 2001 From: Harrison Healey Date: Thu, 10 Aug 2023 13:01:51 -0400 Subject: [PATCH 081/102] MM-41813 Fix path to fonts loaded by plugin --- mattermost-plugin/webapp/webpack.config.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mattermost-plugin/webapp/webpack.config.js b/mattermost-plugin/webapp/webpack.config.js index 271b98fd2..51a66d168 100644 --- a/mattermost-plugin/webapp/webpack.config.js +++ b/mattermost-plugin/webapp/webpack.config.js @@ -112,13 +112,21 @@ const config = { exclude: [/node_modules/], }, { - test: /\.(png|eot|tiff|svg|woff2|woff|ttf|jpg|gif)$/, + test: /\.(png|eot|tiff|svg|ttf|jpg|gif)$/, type: 'asset/resource', generator: { filename: '[name][ext]', publicPath: TARGET_IS_PRODUCT ? undefined : '/static/', } }, + { + test: /\.(woff2|woff)$/, + type: 'asset/resource', + generator: { + filename: '[name][ext]', + publicPath: TARGET_IS_PRODUCT ? undefined : '/plugins/focalboard/static/', + } + }, ], }, devtool, From a0639e7a718b62b7a5490bec23f25dfd12ec4ab1 Mon Sep 17 00:00:00 2001 From: Eric Sethna Date: Mon, 14 Aug 2023 15:26:02 -0700 Subject: [PATCH 082/102] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9ec4739f2..eb57f527a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # :warning: Announcement: PLEASE READ :warning: -Focalboard Personal Server and Personal Desktop editions will transition to being fully community supported as of **April 30th, 2023**. This Focalboard repository will become the Personal Edition repository, and will remain open indefinitely. However, we won’t be adding any new enhancements, and will only address Sev-1 level bugs until April 30th, 2023. +Focalboard will transition to being fully community supported as of **September 15th, 2023**. This Focalboard repository will remain open indefinitely; however, Mattermost won’t be adding any new enhancements, and will only address Sev-1 level bugs until September 15th, 2023. # Focalboard @@ -19,7 +19,7 @@ Focalboard is an open source, multilingual, self-hosted project management tool It helps define, organize, track and manage work across individuals and teams. Focalboard comes in three editions: -* **[Mattermost Boards](https://mattermost.com/boards/)**: Integrated with the Mattermost platform for your team to plan and collaborate. +* **[Mattermost plugin](https://github.com/mattermost/focalboard/releases)**: Download and install the the focalboard plugin for existing your Mattermost instance. * **[Personal Desktop](https://www.focalboard.com/docs/personal-edition/desktop/)**: A standalone, single-user [macOS](https://apps.apple.com/app/apple-store/id1556908618?pt=2114704&ct=website&mt=8), [Windows](https://www.microsoft.com/store/apps/9NLN2T0SX9VF?cid=website), or [Linux](https://www.focalboard.com/download/personal-edition/desktop/#linux-desktop) desktop app for your own todos and personal projects. @@ -27,9 +27,9 @@ It helps define, organize, track and manage work across individuals and teams. F ## Try Focalboard -### Mattermost Boards +### Mattermost Plugin -**Mattermost Boards** combines project management tools with messaging and collaboration for teams of all sizes. To access and use **Mattermost Boards**, install or upgrade to Mattermost v6.0 or later as a [self-hosted server](https://docs.mattermost.com/guides/deployment.html?utm_source=github&utm_campaign=focalboard). After logging into Mattermost, select the menu in the top left corner and select **Boards**. +The **Focalboard plugin** integrates into an exsting Mattermost instance to combine project management tools with messaging and collaboration for teams of all sizes. After downloading and installing the plugin in the System Console, select the menu in the top left corner and select **Boards**. Access the latest releases of the focalboard plugin by downloading the `mattermost-plugin-focalboard.tar.gz` file from the releases in this repository: https://github.com/mattermost/focalboard/releases ### Personal Desktop (Windows, Mac or Linux Desktop) From f6036cd662ca1660afb2b28635c456aeef6ed9ec Mon Sep 17 00:00:00 2001 From: Eric Sethna Date: Mon, 14 Aug 2023 15:28:45 -0700 Subject: [PATCH 083/102] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index eb57f527a..06f61a81b 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Focalboard is an open source, multilingual, self-hosted project management tool It helps define, organize, track and manage work across individuals and teams. Focalboard comes in three editions: -* **[Mattermost plugin](https://github.com/mattermost/focalboard/releases)**: Download and install the the focalboard plugin for existing your Mattermost instance. +* **[Focalboard plugin](https://github.com/mattermost/focalboard/releases)**: The Focalboard plugin integrates into an exsting Mattermost instance to combine project management tools with messaging and collaboration for teams of all sizes. * **[Personal Desktop](https://www.focalboard.com/docs/personal-edition/desktop/)**: A standalone, single-user [macOS](https://apps.apple.com/app/apple-store/id1556908618?pt=2114704&ct=website&mt=8), [Windows](https://www.microsoft.com/store/apps/9NLN2T0SX9VF?cid=website), or [Linux](https://www.focalboard.com/download/personal-edition/desktop/#linux-desktop) desktop app for your own todos and personal projects. @@ -29,7 +29,7 @@ It helps define, organize, track and manage work across individuals and teams. F ### Mattermost Plugin -The **Focalboard plugin** integrates into an exsting Mattermost instance to combine project management tools with messaging and collaboration for teams of all sizes. After downloading and installing the plugin in the System Console, select the menu in the top left corner and select **Boards**. Access the latest releases of the focalboard plugin by downloading the `mattermost-plugin-focalboard.tar.gz` file from the releases in this repository: https://github.com/mattermost/focalboard/releases +After downloading and installing the plugin in the System Console, select the menu in the top left corner and select **Boards**. Access the latest releases of the focalboard plugin by downloading the `mattermost-plugin-focalboard.tar.gz` file from the releases in this repository: https://github.com/mattermost/focalboard/releases ### Personal Desktop (Windows, Mac or Linux Desktop) From 556a9f80fbc57c396b4c0ed9abb06d5ea00a7925 Mon Sep 17 00:00:00 2001 From: Eric Sethna Date: Mon, 11 Sep 2023 11:29:25 -0700 Subject: [PATCH 084/102] Update README.md Clarify community support and link to forum post --- README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 06f61a81b..45008bb76 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,14 @@ -# :warning: Announcement: PLEASE READ :warning: -Focalboard will transition to being fully community supported as of **September 15th, 2023**. This Focalboard repository will remain open indefinitely; however, Mattermost won’t be adding any new enhancements, and will only address Sev-1 level bugs until September 15th, 2023. +# :warning: Announcements + +Effective September 15th, 2023, the Focalboard plugin will no longer be bundled with Mattermost and will transition to being fully community supported. + +Self-hosted Mattermost instances may continue to use the Focalboard plugin without interruption; however, Mattermost developers will not be adding any new enhancements or bug fixes beyond September 15th, 2023. This Focalboard repository will remain open indefinitely for contributions from the open source community. + +The reason behind these changes is to focus Mattermost developer resources on improving the platform’s performance and core features to ensure Mattermost continues being resilient, stable, and best-in-breed for critical operations. + +You can [learn more about these changes in our forum](https://forum.mattermost.com/t/upcoming-product-changes-to-boards-and-various-plugins/16669). + + # Focalboard @@ -129,7 +138,7 @@ Before checking in commits, run `make ci`, which is similar to the `.gitlab-ci.y ### Translating -Help translate Focalboard! The app is already translated into several languages. We welcome corrections and new language translations! You can add new languages or improve existing translations at [Weblate](https://translate.mattermost.com/engage/focalboard/). +Help translate Focalboard! The plugin is already translated into several languages. We welcome corrections and new language translations submitted against the [appropriate language JSON file](https://github.com/mattermost/focalboard/tree/main/webapp/i18n) in this repository. ### Staying informed From 277ea9facc494ad577106e4a0db533d9f7dcaad4 Mon Sep 17 00:00:00 2001 From: "Carrie Warner (Mattermost)" <74422101+cwarnermm@users.noreply.github.com> Date: Thu, 14 Sep 2023 13:35:28 -0400 Subject: [PATCH 085/102] Transitioning Mattermost Boards > Focalboards plugin docs (#4862) * Transitioning Boards > Focalboards plugin docs * Update docs/focalboard-plugin-end-user-guide.md * Update docs/get-started-with-board-templates.md * Update docs/get-started-with-board-templates.md * Update docs/group-filter-sort-boards.md * Update docs/group-filter-sort-boards.md * Update docs/share-collaborate.md * Update docs/import-export-backup-data.md * Update docs/import-export-backup-data.md * Fix MD table fomatting * Added data collection content * Added Focalboard import notes --- docs/board-metrics.md | 55 ++++++ docs/create-new-board.md | 17 ++ docs/dev-tips.md | 4 +- ...s-dev-guide.md => focalboard-dev-guide.md} | 8 +- docs/focalboard-plugin-end-user-guide.md | 23 +++ docs/get-started-with-board-templates.md | 47 +++++ docs/group-filter-sort-boards.md | 79 +++++++++ docs/import-export-backup-data.md | 147 ++++++++++++++++ docs/index.md | 28 ++- docs/link-boards-to-mattermost-channels.md | 24 +++ docs/manage-boards.md | 39 +++++ docs/manage-plugin-preferences.md | 5 + docs/plugin-data-being-collected.md | 46 +++++ docs/share-collaborate.md | 93 ++++++++++ docs/work-with-board-views.md | 35 ++++ docs/work-with-cards.md | 164 ++++++++++++++++++ 16 files changed, 805 insertions(+), 9 deletions(-) create mode 100644 docs/board-metrics.md create mode 100644 docs/create-new-board.md rename docs/{mattermost-boards-dev-guide.md => focalboard-dev-guide.md} (86%) create mode 100644 docs/focalboard-plugin-end-user-guide.md create mode 100644 docs/get-started-with-board-templates.md create mode 100644 docs/group-filter-sort-boards.md create mode 100644 docs/import-export-backup-data.md create mode 100644 docs/link-boards-to-mattermost-channels.md create mode 100644 docs/manage-boards.md create mode 100644 docs/manage-plugin-preferences.md create mode 100644 docs/plugin-data-being-collected.md create mode 100644 docs/share-collaborate.md create mode 100644 docs/work-with-board-views.md create mode 100644 docs/work-with-cards.md diff --git a/docs/board-metrics.md b/docs/board-metrics.md new file mode 100644 index 000000000..805bf376e --- /dev/null +++ b/docs/board-metrics.md @@ -0,0 +1,55 @@ +# Board metrics + +When you view a board in table or board view, you can use calculations to answer basic metric questions without needing to create complex reports. Hover over the bottom of a column to display the **Calculate** feature, then select the arrow to open the menu options. + +You can use calculations to quickly see: + +- How many story points are planned for a release. +- How many tasks have been assigned or not assigned. +- How long has the oldest bug been sitting in the backlog. +- The count of cards where particular properties are empty (useful to make sure important info isn’t missing). +- The sum of estimated developer days for features (to make sure your team isn’t overloaded). +- The range of estimated dates (to make sure your milestones all line up). + +The calculation options are: + +* **Count**: Counts the total number of rows in table view or total number of cards in a column in Board view. Applies to any property type. +* **Count Empty**: Applies to any property type. + + - Table View: Counts the total number of empty rows per column selected. + - Board View: Counts the total number of empty values per property specified within the same column. + +* **Count Not Empty**: Applies to any property type. + + - Table View: Counts the total number of rows with non-empty cells per column selected. + - Board View: Counts the total number of non-empty values per property specified within the same column. + +* **Percent Empty**: Applies to any property type. + + - Table View: Percentage of empty rows per column selected. + - Board View: Percentage of empty values per property specified within the same column. + +* **Percent Not Empty**: Applies to any property type. + + - Table View: Percentage of rows with non-empty cells per column selected. + - Board View: Percentage of non-empty values per property specified within the same column. + +* **Count Value**: Applies to any property type. + + - Table View: Counts the total number of values within the column (helpful for multi-select properties). + - Board View: Counts the total number of values per property specified within the same column. + +* **Count Unique Values**: Applies to any property type. + + - Table View: Counts the total number of rows with unique values within the column, omitting any duplicates from the count. + - Board View: Counts the total number of unique values per property specified within the same column, omitting any duplicates from the count. + +* **Sum**: The sum of any specified number property within the same column. +* **Average**: The average of any specified number property within the same column. +* **Median**: The median of any specified number property within the same column. +* **Min**: The lowest number of any specified number property within the same column. +* **Max**: The highest number of any specified number property within the same column. +* **Range**: Displays the lowest and highest number. Requires a number property. +* **Earliest Date**: Displays the oldest date. Requires any custom date property or the included "Created time" or "Last updated time". +* **Latest Date**: Displays the most recent date. Requires any custom date property or the included "Created time" or "Last updated time". +* **Date Range**: The difference between the most recent date and oldest date within the same column. In Table View, it's labeled simply as "Range" for any date property/column. Requires any custom date property or the included "Created time" or "Last updated time". diff --git a/docs/create-new-board.md b/docs/create-new-board.md new file mode 100644 index 000000000..eabab1a18 --- /dev/null +++ b/docs/create-new-board.md @@ -0,0 +1,17 @@ +# Create a new board + +If none of the standard templates suit your requirements, you can create a blank board. Select the plus icon at the top of the sidebar, then select **Create New Board** to open the template picker and select the **Create empty board** option. + +## Manage board details + +If you've created a board, you can edit that board any time. To name or rename a board, select the title area to edit it. + +To display board description, hover above the board’s title and select **Show description** to activate the show/hide toggle. Once the description field is displayed, select **Add a description** right below the board title to add or edit the description. + +Boards and cards are created with random icons by default. To change or remove icons, select the icon then choose the appropriate action. + +All changes you make to boards and cards are saved immediately. + +## Create a template from a board + +To turn an existing board into a template, hover over the board title in the sidebar. Select the options menu, then select **New template from board**. diff --git a/docs/dev-tips.md b/docs/dev-tips.md index ef070aeff..03bb44bdc 100644 --- a/docs/dev-tips.md +++ b/docs/dev-tips.md @@ -1,6 +1,8 @@ # Developer Tips and Tricks -These tips and tricks apply to developing the standalone Personal Server of Focalboard. For most features, this is the easiest way to get started working against code that ships across editions. For working with Mattermost Boards, refer to the [Mattermost Boards developer's guide](mattermost-boards-dev-guide.md). +These tips and tricks apply to developing the standalone Personal Server of Focalboard. For most features, this is the easiest way to get started working against code that ships across editions. + +For working with the Focalboard plugin, refer to the [Focalboard Plugin Developer's Guide](focalboard-dev-guide.md). ## Installation prerequisites diff --git a/docs/mattermost-boards-dev-guide.md b/docs/focalboard-dev-guide.md similarity index 86% rename from docs/mattermost-boards-dev-guide.md rename to docs/focalboard-dev-guide.md index a23bd904b..2628d0245 100644 --- a/docs/mattermost-boards-dev-guide.md +++ b/docs/focalboard-dev-guide.md @@ -1,6 +1,6 @@ -# Mattermost Boards Developer's Guide +# Focalboard Plugin Developer's Guide -[Mattermost Boards](https://mattermost.com/boards/) is the Focalboard (aka Boards) plugin running in Mattermost. It is pre-packaed, and runs out of the box with Mattermost 6.0 and later. +**Important**: Effective September 15th, 2023, Mattermost Boards transitions to being fully community supported as the Focalboard Plugin. Mattermost will no longer be maintaining this plugin - this includes bug fixes and feature additions. Instead, the plugin is open-sourced and made available indefinitely for community contributions in GitHub. To build your own version of it: 1. Build [mattermost-plugin](https://github.com/mattermost/focalboard/tree/main/mattermost-plugin) in the [Focalboard repo](https://github.com/mattermost/focalboard) @@ -8,7 +8,7 @@ To build your own version of it: Here are the steps in more detail: -### Building the Boards plugin +### Building the Focalboard plugin Fork the [Focalboard repo](https://github.com/mattermost/focalboard), clone it locally, and follow the steps in the readme to set up your dev environment. @@ -55,7 +55,7 @@ First, build and run Mattermost locally: 5. Add an ENV var `MM_SERVICESETTINGS_SITEURL` with the same site URL used in the config 6. Run `make run-server` in Mattermost -Now, to build and deploy the Boards plugin: +Now, to build and deploy the plugin: 1. Clone / fork [mattermost/focalboard](https://github.com/mattermost/focalboard) 2. Install the dependencies (see above) 3. Run: diff --git a/docs/focalboard-plugin-end-user-guide.md b/docs/focalboard-plugin-end-user-guide.md new file mode 100644 index 000000000..d1588f4f4 --- /dev/null +++ b/docs/focalboard-plugin-end-user-guide.md @@ -0,0 +1,23 @@ +# Focalboard Plugin End User's Guide + +The Focalboard plugin is a deliverable and task management solution to help teams achieve project milestones using a familiar kanban board structure. + +This user guide is for anyone looking to use Focalboard to: +- Align work across the organization and drive milestone achievement such as project planning, execution, and task management. +- Keep everyone in your team and organization in the loop to stay on schedule with clearly defined tasks, owners, checklists, and deadlines. +- Increase transparency and keep all resources available including documents, images, and important hyperlinks. +- Track tasks for sprints and features in roadmap planning. + +The following end user documentation is available: + +- [Get started with board templates](get-started-with-board-templates.md) +- [Create a new board](create-new-board.md) +- [Link boards to Mattermost channels](link-boards-to-mattermost-channels.md) +- [Manage boards](manage-boards.md) +- [Work with cards](work-with-cards.md) +- [Work with board views](work-with-board-views.md) +- [Group, filter, and sort boards](group-filter-sort-boards.md) +- [Board metrics](board-metrics.md) +- [Share and collaborate](share-collaborate.md) +- [Import, export, and back up boards data](import-export-backup-data.md) +- [Manage plugin preferences](manage-plugin-preferences.md) diff --git a/docs/get-started-with-board-templates.md b/docs/get-started-with-board-templates.md new file mode 100644 index 000000000..a070422ff --- /dev/null +++ b/docs/get-started-with-board-templates.md @@ -0,0 +1,47 @@ +# Get started with board templates + +## What's a board? + +A board is a collection of cards to help you manage your projects, organize tasks, and collaborate with your team all in one place. A board contains cards, which typically track tasks or topics, and views, which define how to display the cards, or a subset of them. + +Boards can be displayed and filtered in different views such as kanban, table, calendar, and gallery views to help you visualize work items in the format that makes most sense to you. + +## Start from a board template + +To create a new board, we strongly recommend starting from a standard board template. + +Board templates provide you with a predefined structure so that you can get started quickly. Each template has a different function, but can be customized to suit your use case. When you create a new board from the template picker, select each template’s name to preview it and make sure it suits your requirements. Alternatively, you can create your own board templates. + +Select the plus icon at the top of the sidebar, then select **Create New Board** to open the template picker and select a template or a blank board. + +Standard board templates include: + +- **Content Calendar**: Plan and organize your content creation and publication schedule. +- **Company Goals & OKRs**: Plan your company goals and objectives more efficiently. +- **Competitive Analysis**: Track and stay ahead of the competition. +- **Meeting Agenda**: Use this template for recurring meetings. Queue up items, organize discussions, and plan what to revisit later. +- **Personal Goals**: Categorize and plan your personal goals. +- **Personal Tasks**: Organize your life and track your personal tasks. +- **Project Tasks**: Stay on top of your project tasks, track progress, and set priorities. +- **Roadmap**: Plan your roadmap and manage your releases more efficiently. +- **Sprint Planner**: Plan your sprints and releases more efficiently. +- **Team Retrospective**: Identify what worked well and what can be improved for the future. +- **User Research Sessions**: Manage and keep track of all your user research sessions. +- **Welcome to Boards!**: Onboarding template with guided tour points to help you quickly ramp up on Focalboard. + +### Edit board templates + +To open the template editor for a specific template, go to the template picker then hover over the custom template and select the pencil icon. Any changes made on the template editor will be automatically saved and visible to team members who have access to the template. If you don't see the pencil icon when hovering over the template, then you don't have the appropriate permissions to edit the template. + +**Notes**: +- From v7.2 of the Focalboard plugin, only admins and editors of a custom template can edit the template. +- Prior to v7.2 of the plugin, any member of the channel workspace can edit a custom template in the channel. To limit access to the template, create or export the template to a private channel. +- Custom templates are fully editable, but standard templates cannot be edited or deleted. + +## Create a template + +To create a new board template select the plus icon at the top of the sidebar to open the template picker, select **Create New Board** and then select **+ New template**. + +## Turn a board into a template + +To turn an existing board into a template, hover over the board title in the sidebar. Select the options menu, then select **New template from board**. diff --git a/docs/group-filter-sort-boards.md b/docs/group-filter-sort-boards.md new file mode 100644 index 000000000..f0c74d0f2 --- /dev/null +++ b/docs/group-filter-sort-boards.md @@ -0,0 +1,79 @@ +# Group, filter, and sort boards + +Your boards can be grouped, filtered, and sorted into different views using a range of properties. This gives you a powerful way to track work from various perspectives. For example, easily find tasks assigned to you or a team member using the person or multi-person filters, and keep track of upcoming tasks with date filters. + +## Group cards + +You can group cards on your board if they utilize the **Select** or **Person** property. + +Card grouping is only available in board and table views and you must have at least one **Select** or **Person** property on your board for grouping to work. + +### Apply a group + +To apply a group, select the **Group by** option at the top of the board, then select any available **Select** or **Person** property to group your cards by. + +- In the boards view, cards are automatically grouped into columns by the values from the specified property. +- In the table view, grouped cards will appear in individual sections based on the values from the specified property. Select the arrow to the left of the group name to expand or collapse cards in the group. + +### Hide and unhide groups + +- To hide a group, select the options menu **(...)** to the right of any group name, then select **Hide**. Additionally, in table view only, you can hide empty groups by selecting the **Group by** option at the top of the board, then selecting **Hide empty groups**. +- To unhide a group, go to the hidden column section towards the right of a board view, select the group you want to unhide, then select **Show**. On table view, select the **Group by** option at the top of the board, then select **Show hidden groups**. + +### Ungroup cards + +To ungroup cards on table view, select the **Group by** option at the top of the board, then select **Ungroup** from the top of the menu. This will return your table to its default state. Cards can be ungrouped in table view only. Ungrouping is not possible on board view since groups are used to determine what to display. + +## Filter cards + +You can filter cards on your board if they utilize any of the following property types: + +- Select +- Text +- Email +- Phone +- URL +- Date +- Person +- Multi-person +- Created time +- Created by +- Last updated time +- Last updated by + +You must have at least one of the property types listed above on your board for filtering to work. + +To use filters, you must have the above property types already added to your board. Go to **Filter > Add filter**, and select the property you wish to filter by. You can use the modifiers to get even more granular results. + +### Add filters + +To add a filter, select the **Filter** option at the top of the board, then select **+ Add filter**. To change the property to filter by, select the name of the first property, then select another property (if available) from the menu. + +**Specify the filtering criteria** + +- **Includes**: Display cards with any of the specified values. +- **Doesn’t include**: Display all cards without any of the specified values. +- **Is empty**: Display cards with no values assigned to a property. +- **Is not empty**: Display cards with any value assigned to a property. + +To add another filtering layer, repeat the steps above with another property to refine your filtering results. Adding another layer will display cards that only match the criteria from the first layer and the second layer. + +### Delete filters + +To delete a filter, select the **Filter** option at the top of the board, then select **Delete** to the right of each filtering layer. Delete all filtering layers to completely remove filters from the board. + +## Sort cards + +Sort cards by the card name or by any property available on the card. + +Sorting is only available in boards, table, and gallery views. + +### Apply sorting + +To apply a sort, select the **Sort** option at the top of the board, then select an option from the menu. The cards will be sorted in ascending order by default based on the selected option and the **Sort** menu will display an upward pointing arrow next to the selected option. + +To change the sort order to descending order, select the same option again from the **Sort** menu. The cards will now be sorted in descending order and the menu will display a downward pointing arrow next to the selected option. + +### Clear sorting + +To clear a sort, select the **Sort** option at the top of the board, then select the **Manual** option from the top of the menu. diff --git a/docs/import-export-backup-data.md b/docs/import-export-backup-data.md new file mode 100644 index 000000000..fb88b0522 --- /dev/null +++ b/docs/import-export-backup-data.md @@ -0,0 +1,147 @@ +# Import, export, and back up data + +## Import data into Focalboard + +You can import data from other tools to use with Focalboard. + +### Import from Asana + +This node app converts an Asana JSON archive into a ``.boardarchive`` file. The script imports all cards from a single board, including their section (column) membership, names, and notes. + +1. Log into your Asana account. +2. Select the drop-down menu next to the Asana board's name. Then select **Export/Print > JSON**. This will create an archive file. +3. Save the file locally, e.g. to ``asana.json``. +4. Open a terminal window on your local machine and clone the focalboard repository to a local directory, e.g. to ``focalboard``: ``git clone https://github.com/mattermost/focalboard focalboard`` +5. Navigate to ``focalboard/webapp``. +6. Run ``npm install``. +7. Change directory to ``focalboard/import/asana``. +8. Run ``npm install``. +9. From within the same folder, run ``npx ts-node importAsana.ts -i -o archive.boardarchive``. This generates the following data: + + ``` + My-MacbookPro:asana macbook$ npx ts-node importAsana.ts -i ~/Downloads/asana.json -o archive.boardarchive + Board: 1:1 Meeting Agenda Test + Card: [READ ME] Instructions for using this project + Card: [EXAMPLE TASK] Feedback on design team presentation + Card: [EXAMPLE TASK] Finalize monthly staffing plan + Card: [EXAMPLE TASK] Review Q2 launch video outline + Card: [EXAMPLE TASK] Mentor a peer + + Found 5 card(s). + Exported to archive.boardarchive + ``` + +10. In Focalboard, open the board you want to use for the export. +11. Select **Settings > Import archive** and select ``archive.boardarchive``. +12. Select **Upload**. +13. Return to your board and confirm that your Asana data is now displaying. + +If you don't see your Asana data, an error should be displayed. You can also check log files for errors. + +### Import from Notion + +This node app converts a Notion CSV and markdown export into a ``.boardarchive`` file. The script imports all cards from a single board, including their properties and markdown content. + +**Note**: The Notion export format does not preserve property types, so the script currently imports all card properties as a Select type. You can change the type after importing into Focalboard. + +1. From a Notion Board, open the **...** menu at the top right corner of the board. +2. Select `Export` and pick `Markdown & CSV` as the export format. +3. Save the generated file locally, and unzip the folder. +4. Open a terminal window on your local machine and clone the focalboard repository to a local directory, e.g. to ``focalboard``: ``git clone https://github.com/mattermost/focalboard focalboard`` +5. Navigate to ``focalboard/webapp``. +6. Run ``npm install``. +7. Change directory to ``focalboard/import/notion``. +8. Run ``npm install``. +9. From within the same folder, run ``npx ts-node importNotion.ts -i -o archive.boardarchive``. +10. In Focalboard, open the board you want to use for the export. +11. Select **Settings > Import archive** and select ``archive.boardarchive``. +12. Select **Upload**. +13. Return to your board and confirm that your Notion data is now displaying. + +### Import from Jira + +This node app converts a Jira ``.XML`` export into a ``.boardarchive`` file. The script imports each item as a card into a single board. Users are imported as Select properties, with the name of the user. + +**Notes**: +- Jira ``.XML`` export is limited to 1000 issues at a time. +- The following aren't currently imported: custom properties, comments, and embedded files. + +1. Open Jira advanced search, and search for all the items to export. +2. Select **Export > Export XML**. +3. Save the generated file locally, e.g. to ``jira_export.xml``. +4. Open a terminal window on your local machine and clone the focalboard repository to a local directory, e.g. to ``focalboard``: ``git clone https://github.com/mattermost/focalboard focalboard`` +5. Navigate to ``focalboard/webapp``. +6. Run ``npm install``. +7. Change directory to ``focalboard/import/jira`. +8. Run ``npm install``. +9. From within the same folder, run ``npx ts-node importJira.ts -i -o archive.boardarchive``. +10. In Focalboard, open the board you want to use for the export. +11. Select **Settings > Import archive** and select ``archive.boardarchive``. +12. Select **Upload**. +13. Return to your board and confirm that your Jira data is now displaying. + +### Import from Trello + +This node app converts a Trello ``.json`` archive into a ``.boardarchive`` file. The script imports all cards from a single board, including their list (column) membership, names, and descriptions. + +1. From the Trello Board Menu, select **...Show Menu**. +2. Select **More > Print and Export > Export to JSON**. +3. Save the generated file locally, e.g. to ``trello.json``. +4. Open a terminal window on your local machine and clone the focalboard repository to a local directory, e.g. to ``focalboard``: ``git clone https://github.com/mattermost/focalboard focalboard`` +5. Navigate to ``focalboard/webapp``. +6. Run ``npm install``. +7. Change directory to ``focalboard/import/trello``. +8. Run ``npm install``. +9. From within the same folder, run ``npx ts-node importTrello.ts -i -o archive.boardarchive``. +10. In Focalboard, open the board you want to use for the export. +11. Select **Settings > Import archive** and select ``archive.boardarchive``. +12. Select **Upload**. +13. Return to your board and confirm that your Trello data is now displaying. + +### Import from Todoist + +This node app converts a Todoist ``.json`` archive into a ``.boardarchive`` file. + +1. Visit the open source Todoist data export service at https://darekkay.com/todoist-export/. +2. From the **Options** menu, select **Export As > JSON (all data)**. +3. Uncheck the **Archived** option if checked. +4. Select **Authorize and Backup**. This will take you to your Todoist account. Follow the instructions on screen. +5. Note the name and location of the downloaded ``.json`` file. +6. Open a terminal window on your local machine and clone the focalboard repository to a local directory, e.g. to ``focalboard``: ``git clone https://github.com/mattermost/focalboard focalboard`` +7. Navigate to ``focalboard/webapp``. +8. Run ``npm install``. +9. Change directory to ``focalboard/import/todoist``. +10. Run ``npm install``. +11. From within the same folder, run ``npx ts-node importTodoist.ts -i -o archive.boardarchive``. +12. In Focalboard, open the board you want to use for the export. +13. Select **Settings > Import archive** and select ``archive.boardarchive``. +14. Select **Upload**. +15. Return to your board and confirm that your Todoist data is now displaying. + +## Export from Focalboard + +You can export your boards data as a CSV file. + +1. Select the options menu to the left of the **New** button at the top of any board. +2. Select **Export to CSV**. +3. Import the CSV file to your tool of choice. The CSV file contains all the cards in that board and their associated properties. + +**Notes**: + +- If you only see a single entry in the CSV export when the board contains multiple cards, you may have a specific card in context when you exported the file because you were performing a card search. If you have searched for a card, and that card is in context, that’s the only card that will be exported into the CSV file. Clear your search and try exporting to CSV again. +- After importing CSV Focalboard data from one Mattermost instance into another (such as during a migration from Mattermost Cloud to self-hosted), card timestamps will be updated based on the import date, and cards won't correctly identify users whose user IDs differ across Mattermost instances. + +## Back up your Focalboard data + +If you’d like to back up a board, you can export it as an archive file. You can import that board to another Mattermost team within the same Mattermost instance. Exported and imported board archives include all card content such as properties, comments, descriptions, and image attachments. + +1. Select the options menu Options icon to the left of the **New** button at the top of the board +2. Select **Export board archive**. +3. Download the archive file. +4. Navigate to the team or channel workspace where you’d like to add the exported board. +5. Select the Gear icon next to your profile picture, then choose **Import archive**. The board you exported will be added to this team or channel workspace. + +**Notes**: + +- If you're using a version of the Focalboard plugin older than v6.4, backing up a board results in a ``.focalboard`` file, rather than a ``.boardarchive`` file. When importing a board backup, select the **Select all files** option to select ``.focalboard`` files. +- After importing a Focalboard backup from one Mattermost instance into another (such as during a migration from Mattermost Cloud to self-hosted), card timestamps will be updated based on the import date, and cards won't correctly identify users whose user IDs differ across Mattermost instances. diff --git a/docs/index.md b/docs/index.md index 6fbb54f42..8d14bf3fc 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,10 +1,30 @@ -# Focalboard / Mattermost Boards Contributors Guide +# Focalboard Plugin Documentation -Welcome to the [Focalboard](https://www.focalboard.com) / [Mattermost Boards](https://mattermost.com/boards/?utm_source=focalboard) project! +Welcome to the Focalboard plugin project! We're very glad you want to check it out and perhaps contribute code to this project in GitHub. -We're very glad you want to check it out and perhaps contribute code our repository in GitHub. +## Install the plugin -Our goal is to make your experience as great as possible. Follow these simple steps to contribute: +Visit the [Mattermost Developer Documentation](https://developers.mattermost.com/integrate/plugins/using-and-managing-plugins/#custom-plugins) for details on how to install and enable the Focalboard plugin in your self-hosted Mattermost instance. + +## Enable the plugin + +Once you've installed the Focalboard plugin, you can enable the plugin in the Mattermost System Console by going to **Plugins > Plugin Management**, and selecting the **Enable** option for the Focalboard plugin. + +## Learn what Focalboard plugin data is being collected + +See the [plugin data being collected documentation](plugin-data-being-collected.md) for details. + +## Use the plugin + +See the [Focalboard plugin end user guide](focalboard-plugin-end-user-guide.md) for details on getting started with and using the plugin. + +## Manage plugin preferences + +See the [manage plugin preferences documentation](manage-plugin-preferences.md) for details. + +## Contribute to the Focalboard plugin project + +Follow these simple steps to contribute: 1. [Fork the Focalboard repo](https://github.com/mattermost/focalboard), clone it locally, and follow the steps in the README to build. Read the [developer tips & tricks](dev-tips.md) to get started. diff --git a/docs/link-boards-to-mattermost-channels.md b/docs/link-boards-to-mattermost-channels.md new file mode 100644 index 000000000..0b37a2270 --- /dev/null +++ b/docs/link-boards-to-mattermost-channels.md @@ -0,0 +1,24 @@ +# Link boards to Mattermost channels + +## Link a board to a channel + +Boards can be linked to channels and accessed from the channel Apps Bar. + +1. Select the **Focalboard** icon from the Apps Bar in a channel to open a right-hand sidebar (RHS). +2. Search for and link boards to the channel. +3. Select **Add** button to open the link boards dialog and search for a board to link. + +Once a board is linked to a channel, it's listed in the right-hand pane. Linking a board to a channel automatically grants all channel members access to the board, with the exception of guest accounts. Select a linked board to navigate directly to the board. + +**Notes**: +- A channel can be linked to multiple boards, but each individual board can only be linked to one channel at a time. +- Linking the same board to another channel will automatically replaces the link to the previous channel with the new channel. +- Channel members can only search and link boards within the team where they are a board admin. +- If you're using a Focalboard plugin older than v7.2, you won't be able to link a board to a channel. We recommend upgrading to the latest version of the plugin to take full advantage of all plugin features and functionality. +- After upgrading to version v7.2 or later of the Focalboard plugin, your boards automatically appear in the right-hand side pane for easy access. + +## Unlink a board from a channel + +If you're a board admin, and want to unlink a board from a channel you're in, open linked board, select the options menu, and select **Unlink**. + +Alternatively, you can open the **Share** dialog on the board, open the **Role** drop-down menu next to the channel's name and select **Unlink**. diff --git a/docs/manage-boards.md b/docs/manage-boards.md new file mode 100644 index 000000000..d41dfb32a --- /dev/null +++ b/docs/manage-boards.md @@ -0,0 +1,39 @@ +# Manage boards + +## Access your boards + +Open the Boards tab via the product menu in the top left corner of Mattermost to view all the boards for your team. You can select the **Focalboard** icon in the Apps Bar to open the right-hand panel, and display boards linked to the channel or message that you're in. + +If you don't see the Apps Bar and your boards layout looks different to what's described, you may be using an older version of Mattermost and/or the Focalboard plugin. + +## Find a board + +From the top of the boards left hand sidebar, select the **Find Boards** field (CMD+K/CTRL+K) to open the board switcher, and start typing the name of the board you’re looking for. + +## Manage sidebar categories + +From Focalboard plugin v7.2, you can organize your boards in the left-hand sidebar using custom categories. By default, all boards will appear under the **Boards** category. To manage your categories, open the Options menu next to the category to create, delete, or rename a category. With the exception to the default **Boards** category, all other categories can be renamed or deleted. + +After creating categories, you can move your boards to those categories by opening the Options menu next to the board and selecting **Move To…** to select the category where you want the board to be moved. + +If you delete a category with boards in it, then those boards will return to the default **Boards** category. + +Categories are organized per-user, so you can arrange your boards under categories that make sense to you without impacting boards or categories for other users. If a board is moved to a custom category, then the board will appear under that category for you only. Other users who are members of the board will continue to see the board in their own categories. + +### Organize using drag and drop + +You can organize both sidebar categories and boards to change the order of both to suit your preference. You can: + +- Set the position of a board within a category. +- Drag a board out of one category and drop it into another category. + +To do this, select and hold the cursor over the category or board name. Then move the category or board around as needed. Boards moved into a category are sorted to the top of the category by default unless you specifically position the board before releasing the cursor. + +### Manage boards in the sidebar + +In addition to moving boards to other categories, from the Options menu next to each board name, you can perform the following actions: + +- **Delete board**: If you're an admin of the board, you will see an option to delete the board. Deleting the board permanently removes the board from the sidebar of all board members. +- **Duplicate board**: Creates a copy of the board and all the cards on the board. The duplicated board will appear under the same category as the original board. Board members and comments from the original board aren't migrated to the new board. +- **New template from board**: Creates a custom board template of the board and all the cards on the board. +- **Hide board**: Hides the board from your sidebar only. The board will still remain visible on the sidebar for other board members. You can add the board back to your sidebar using the search box (CMD+K/CTRL+K). diff --git a/docs/manage-plugin-preferences.md b/docs/manage-plugin-preferences.md new file mode 100644 index 000000000..4ebf401ca --- /dev/null +++ b/docs/manage-plugin-preferences.md @@ -0,0 +1,5 @@ +# Manage plugin preferences + +## Disable emojis on cards + +You can enable or disable random emoji icons for your board and cards by selecting the Gear icon next to your profile picture, then toggling **Random icons on or off**. diff --git a/docs/plugin-data-being-collected.md b/docs/plugin-data-being-collected.md new file mode 100644 index 000000000..6f5ad43e2 --- /dev/null +++ b/docs/plugin-data-being-collected.md @@ -0,0 +1,46 @@ +# Plugin data being collected + +Boards metadata is collected and sent to Mattermost every 24 hours. Visit the [Focalboard telemetry file](https://github.com/mattermost/focalboard/blob/main/webapp/src/telemetry/telemetryClient.ts) for information about the action and event data collected. + +Other telemetry information that Mattermost collects includes: + +## Server telemetry + +### Boards Plugin Information + +- Boards Version and Build Number +- Boards Edition +- Operating System for Boards server +- The server diagnostic ID + +### Configuration Information + +- ServerRoot is default server root (``true``/``false``) +- Port is default port (``true``/``false``) +- UseSSL (``true``/``false``) +- Database Type +- Single User (``true``/``false``) + +### User Count Information + +- Registered User Count +- Daily Active User Count +- Weekly Active User Count +- Monthly Active User Count + +### Block Count Information + +- Block Counts By Type + +### Workspace Information + +- Workspace Count + +## Web app event activity + +### Load Board View + +- ``UserID``: Unique identifier of the server. +- ``UserActualID``: Unique identifier of the user who initiated the action. +- ``Event``: Type of the event. Only the ``view`` event is currently monitored. +- ``View Type`` (``board``, ``table``, ``gallery``). diff --git a/docs/share-collaborate.md b/docs/share-collaborate.md new file mode 100644 index 000000000..11129e573 --- /dev/null +++ b/docs/share-collaborate.md @@ -0,0 +1,93 @@ +# Share and collaborate + +You can share boards with your Mattermost teams and within your Mattermost channel conversations. + +## Share a board internally + +To share a board with team members internally, select **Share** in the top-right corner of the board, then select **Copy link** from the **Share** tab below. Paste the copied link in a channel or direct message to share the board with other team members. Only team members who have permissions to the board will be able to open the board from the shared link. + +## Share cards in channel conversations + +Cards can be linked and shared with team members directly with Mattermost Channels. When you share a link to a card within a channel, the card details are automatically displayed in a preview. This preview highlights what the card is about at a glance without having to navigate to it. + +To share a card, you'll need to copy the card link first: + +- Open a card and select the options menu **(...)** at the top right of the card, then select **Copy link**. +- Alternatively, you can open the board view and hover your mouse over any card to access the options menu **(...)** for the card and select **Copy link** from there. + +After you've copied the link, paste it into any channel or direct message to share the card. A preview of the card will display within the channel with a link back to the card on the board. + +## Control access to boards + +Boards belong to teams, and any member of a team can be granted access to a board. + +**Note**: If you're using a Focalboard plugin version prior to v7.2, boards are tied to channel workspaces and board membership is determined by channel membership. In this case, roles and permissions information on this page won't be applicable to you. + +### Board roles + +The level of access to a board is determined by a user’s assigned board role. Individual board membership always gets precedence, followed by highest (most permissive) group role. + +- **Admin**: Can modify the board, its contents, and its permissions. By default, board creators are also admins of the board. +- **Editor**: Can modify the board and its contents. +- **Commenter**: Can add comments to cards. +- **Viewer**: Can view the board and its contents but can't comment or edit the board. + +| **Board permissions** | **Admin** | **Editor** | **Commenter** | **Viewer** | +|------------------------------------|-----------|------------|---------------|------------| +| Modify permissions | X | | | | +| Delete a board | X | | | | +| Rename a board | X | X | | | +| Add, edit, and delete views | X | X | | | +| Add, edit, and delete cards | X | X | | | +| Comment and delete my own comments | X | X | X | | +| Delete any comment | X | | | | +| View a board | X | X | X | X | + +## System admin access + +System admins can access any board across the server provided they have the board's URL without having to request permission or be manually added. When a system admin joins a board, their default role is admin. System admins will have an **Admin** label assigned to their name on the participants list. + +## Team admin access + +Team admins can access any board within their team provided they have the board's URL without having to request permission or be manually added. When a system admin joins a board, their default role is admin. Team admins will have a **Team admin** label assigned to their name on the participants list. + +## Manage team access + +Board admins can manage team access to their board by selecting **Share** in the top-right corner of the board. On the dropdown next to **Everyone at… Team** option, select a minimum board role for everyone on the team. You can also easily assign the new roles to the entire team and/or to individual team members. + +Minimum default board roles reduce permission ambiguity and prevent security loopholes. The minimum default role means that board admins can't assign individual board members a role lower than the team role. If the team role is set to **Editor** then the board admin will only be able to assign the **Editor** or **Admin** role to individual team members. Lower roles will not be available for selection unless the admin changes the minimum board role. + +Depending on the role selected, everyone on the team will have access to the board with a minimum of the permissions from the role selected. Users can get elevated permissions based on their individual board membership. The default team access for a newly created board is **None**, which means nobody on the team has access to the board. + +## Manage individual board membership + +Only board admins can manage user permissions on a board, including adding, changing, and removing members. + +To add individual users from the team as explicit members of the board, open the **Share** dialog on the board, search for individual team members, then assign a role to set their permissions for the board. The role for individual board members overrides any role specified for team access. + +- To change a board member’s role, open the **Share** dialog, select the role dropdown next to the user’s name, then select another role from the list. +- To remove a member from a board, open the **Share** dialog, select the role dropdown next to the user’s name, then select **Remove member**. + +Board admins can also add individual members using the autocomplete list from @mentions and the person properties. To add an individual from the autocomplete list, type their username in an @mention or in the **Person** or **Multi-person** properties, then assign a role to the user from the confirmation dialog, and select **Add to board**. + +On boards with team access, board members with **Editor** or **Commenter** roles can also add individuals to the board from the autocomplete list. Board members added in this manner will be assigned the default minimum board role. + +## Channel role groups + +Board admins can add a channel to a board to grant all its members Editor access. To do this, select **Share** in the top-right corner of the board, search for the channel name, and add it to the board as a user. The default role is Editor. Doing so also [links the board back to the channel](link-boards-to-mattermost-channels) where the board will appear on the channel RHS. + +To unlink the channel from the board, open the **Share** dialog, select the role dropdown next to the channel’s name, then select **Unlink**. + +Remember, a board can only be linked to one channel at a time. Linking another channel to the same board will automatically remove the link from the previous channel. + +## Guest accounts + +From version v7.4 of the Focalboard plugin, [Mattermost guest accounts](https://docs.mattermost.com/onboard/guest-accounts.html#guest-accounts) are supported. If you're not able to access this functionality, you may be on an earlier version of the Focalboard plugin. + +Guests can: + +- Access boards where they're added as an explicit member of the board, but can't manage team access or add channels to boards. +- Access existing boards, but can't create new boards. Guests also don't have access to the template picker and can't duplicate an existing board. +- Search for boards where they're currently an explicit member. +- Be assigned the Viewer, Commenter, or Editor roles, but not the Admin role. +- Only @mention current members on the board. diff --git a/docs/work-with-board-views.md b/docs/work-with-board-views.md new file mode 100644 index 000000000..b5b2f8db6 --- /dev/null +++ b/docs/work-with-board-views.md @@ -0,0 +1,35 @@ +# Work with board views + +Views display your cards in a board, table, calendar, or gallery layout, optionally filtered and grouped by a property (e.g., priority, status, etc). + +To add a new view to a board: + +1. From the board header, select the menu next to the current view name. +2. Scroll down and select **+ Add view**. +3. select the new visualization you’d like to use. + +The following board views are available. + +## Board view + +This is a kanban view where cards are grouped into columns. Column groups only work with the **Select** or **Person** properties and display all cards that share the same value from the specified property. The column names are editable, and any changes to the column names are also applied to the value from the property. Cards can be dragged between columns, which will automatically update the property’s assigned value on the card. + +## Table view + +Displays cards in a table format with rows and columns. Use this view to get an overview of all your project tasks. Easily view and compare the state of all properties across all cards without needing to open individual cards. Each column corresponds to a card property. You can edit cells directly or you can select **Open** to open the card view for that row. + +## Gallery view + +Displays cards in a gallery format, so you can manage and organize cards with image attachments. Gallery view displays a preview of the first image attached on the card. For cards with no image attachments, a preview of the first description block will be displayed instead. + +## Calendar view + +To use this view, cards need to have the **Date** property added. + +If cards don’t have a custom **Date** property, they’ll be sorted and displayed by the card creation date (default). These cards can’t be moved around the board until a custom **Date** property is added. + +If your cards do have a **Date** property and you’re not able to move them around, you may be displaying them by **Created Time** or **Last Updated Time**. + +- To add a new card, select the **+** option in the top-left corner of the relevant date. +- To create a date range event, select a start date and then drag to the end date to create a card for that date range event. +- To add a date range to an existing card, hover over the side of the card to display the arrow and drag to the left or right to create a date range. diff --git a/docs/work-with-cards.md b/docs/work-with-cards.md new file mode 100644 index 000000000..554770355 --- /dev/null +++ b/docs/work-with-cards.md @@ -0,0 +1,164 @@ +# Work with cards + +## What's a card? + +Cards are used on a board to track individual work items. Cards are customizable and can have a number of properties added to them, which are then used as a way to tag, sort, and filter the cards. + +A card consists of: + +- **A set of properties**: Properties are common to all cards in a board. Board views can group cards by “Select” type properties into different columns. +- **A list of comments**: Comments are useful for noting important changes or milestones. +- **A set of content**: The content of a card can consist of Markdown text, checkboxes, and images. Use this to record detailed specs or design decisions for an item for example. + +When working with cards, you can manage properties, add descriptions, attach images, assign them to team members, mention team members, add comments, and so on. + +Standard board templates provide some default card properties that can be customized or removed. In the Roadmap template, there's a **Type** property, whereas in the Project Tasks template, there's an **Estimated Hours** property. These properties are not exclusive to any template and can be easily re-created in any of the templates provided. + +## Add card descriptions + +Card descriptions can include text with Markdown formatting, checkboxes, and visual elements such as images or GIFs, and can be separated into blocks of content. To add a description, open a card, select **Add a description** below the **Comments** section, and start typing in your content. + +To add a new content block in the description section, hover over the section and select **Add content**. Then choose from any of the following options: + +- **Text**: Adds a new text block that can be formatted with Markdown. +- **Image**: Select and embed an image file into the content block. The following image formats are currently supported: GIF, JPEG, and PNG. +- **Divider**: Adds a divider content block below the previous block. +- **Checkbox**: Adds a checkbox content block. Press Enter/Return after typing in content for your checkbox to add another checkbox within the same block. Please note, Markdown formatting isn't supported within the **Checkbox** content block. + +To manage the description content blocks on a card, hover over any existing block and select the options menu |options-icon| to move the block up or down, insert a new block above, or delete the current block. Alternatively, you can hover over any existing block, then select and hold the grid button to drag and drop it to a new position within the description section. + +## Attach files to cards + +From Focalboard plugin version v7.7, you can attach files to your cards, which other board members can download. There are no limitations to the file types that you can upload. + +To upload a file to a card, select **Attach** in the top-right corner of the card. Then select the file you'd like to upload. When your file has been uploaded, you can find it in the **Attachments** section of the card. Select the **+** sign to add additional files to your card. + +To delete a file attachment, hover over it and select the 3-dot menu, then select **Delete**. To download the file, select the download icon. + +## Add card badges + +Card badges are a quick way to view card details without opening up a card. To add them, select **Properties > Comments and Description**. Icons related to the card description, comments, and checkboxes will be displayed on cards with the respective content. Open the card to view the details. + +- The description icon indicates that a card has a text description. +- The comment icon displays a number indicating how many comments have been added to a card. When a new comment is added, that number is updated. +- The checkbox icon displays the number of items checked off relative to the total number of checkboxes within the card. When an item is checked off, the icon is automatically updated. + +## Comment on a card + +Comments allow you to provide feedback and ask questions relevant to the specific work item on the card. + +To add a comment, select a card to open the card view, then click on **Add a comment…** to type in your comment, and press **Send** to save the comment to the card. All team members who are `following the card `_ will receive a notification with a preview of your comment in Mattermost Channels. + +From Focalboard plugin v7.4, only board members with the *Commenter* role or higher can comment on a card. Board members assigned the *Viewer* role can view, but not comment on, a card. + +## Mention people on cards + +You can include a team member on a card by `mentioning them on a card `__ the same way you would in Channels. Mentions are supported in the `Comments `_ and `Description `_ sections within a card. The team member you mention will receive a direct message notification from the boards bot with a link to the card you mentioned them on. To mention multiple team members, separate each name with a comma. + +## Follow card updates + +When you create a card, you automatically follow it. You can @mention someone on a card to add them as a follower. This can be a card you've created or someone else's card. Lastly, you can also follow cards manually using the **Follow** option on the top-right corner of a card. To unfollow a card, select **Following**. + +When updates are made to a card you're following, you'll receive a direct message from the boards bot with a summary of the change (e.g. Bob changed status from **In progress** to **Done**) and a link to the card for more detailed information. + +You won't get a notification of your own changes made to a card, even if you're following that card. + +## Search for cards + +You can search through all the cards on a board to find what you’re looking for. Open the board you want to search, then select the **Search cards** field in the top-right of the board. + +## Manage card properties + +Cards can contain different data fields depending on the purpose of the board. Using card properties, you can customize these data fields to fit your needs and track the information most important to you. For example, in a **Roadmap** board, cards include a **Type** field where you can add categories such as **Bug**, **Epic**, etc. In a **Project Task** board, cards include the **Estimated Hours** field instead. + +Properties are displayed in the order they were created and can't be re-ordered. + +## Create card properties + +To create a new property field open a card and select **Add a property**. Then select the type of property from the drop-down menu. The property type specifies the type of data you plan to capture within that field. When you create new card properties, they're added to all new and all existing cards on the current board. + +Properties are automatically added to the board filter list at the top of the page, so ensure you customize all property names to make it easy to filter your board by specific properties later. + +## Work with property types + +The Focalboard plugin supports a wide range of fully customizable property types: + +- **Text** can be used to add short notes to a card. An advantage of the text property over card descriptions is that it can be `shown on the board `_ without needing to open the card. +- **Numbers** are useful to capture metrics such as task sizing or effort estimates. Use in conjunction with calculations to get the most out of the number property type. +- **Email** and **Phone** can be used to record contact information. +- **URL** can be used to provide a link to a pull request or relevant website. Clicking on the box of a URL property will automatically open the link in a new tab on your browser. Hover over the box to surface options to copy or edit the URL. +- **Select** and **Multi-select** allows you to create a predefined list of options that can be color-coded and displayed as badges on the card to indicate things like status and priority. +- **Dates** are useful to set and track due dates or milestones. Use the date property to make a card appear on the `Calendar view `_. Set a single date or toggle on the **End date** to set a date range. +- **Person** and **Multi-person** provides a quick way to capture user assignments. Note that this is not available in Personal Desktop. +- **Checkbox** is a toggle property that can be used for assigning simple binary options on a card such as True/False or Yes/No. +- **Created time/Created by/Last updated time/Last updated by** are predefined system properties to help you audit changes on a card. The names of these properties are customizable, but the values are not. + +### Rename a property type + +The default name for a new property is the name of the property type (e.g. **Date**, **URL**). +To rename a property field, open up a card and select the property name to open an editable field. Enter the new name in the field provided. The change is saved immediately and applied across all cards on the current board. + +### Change a property type + +To change a property type, select the property then open the **Type** menu and choose a new property type. You’ll be asked to confirm the change from every card on the current board. Changing the type for an existing property will affect values across all cards on the board and may result in data loss. + +### Delete a property + +To delete properties you no longer need, select the property, then choose **Delete**. You’ll be asked to confirm that you want to remove that property from every card on the current board. + +### Define a "Select" or "Multi-select" property + +The options on a **Select** and **Multi-select** property type appear as color-coded tags on a card. Options in a **Select** or **Multi-Select** property list are sorted in the order they were created and can't be re-ordered or renamed. + +To add and configure the options on these types: + +1. Select a card to open the card view. +2. Add a new property, give it a name, and set its type to **Select** (or **Multi-Select**). +3. Select the field box for the property, and start typing the name of a new option. Press Enter to accept. Repeat this step to add additional options. + - To assign a color to or delete an option, select the value and select the options menu **(...)** next to each option name. + - To select an option on the property, select the box and choose one of the values from the menu. + - To remove an option on the property, select the box and chooose the `X` next to the option name you want to remove. + +Alternatively, you can also add new options directly from a board: + +1. Open a board view. +2. Group by a **Select** property. +3. Scroll to the right of the board and select **+ Add a group**. + +This will add a new column, which corresponds to a new value option for the Select property. + +### Control what properties are shown on a board + +Once you have card properties defined, you have full control over which properties are shown on the board as a preview without having to open the card. Select **Properties** at the top of the board, then enable all properties you want to see at a glance, and hide all properties you don’t want to see. + +## Create card templates + +Card templates can help reduce repetitive manual input for similar types of work items. Each board can have any number of card templates. To create a new card template: + +1. Open the board where you want to add the card template. +2. Select the drop-down arrow next to **New**, then select **New template**. +3. Add a title to the card template. +4. Then assign values to any properties and add a description you wish to have pre-populated when a card is created from the template. +5. Close the card using the **X** in the top left corner. +6. Select the drop-down arrow next to **New**, then select the template you just created. + +Alternatively, you can turn any existing card into a template: + +1. Open the card you want to use as a template. +2. Select the options menu |options-icon| in the top-right corner of the card. +3. Select **New template from card**. +4. Edit the card as needed, including a helpful name. +5. Close the card using the **X** in the top left corner. +6. Select the drop-down arrow next to **New**, then select the template you just created. + +To set a default card template for all new cards created on the board: + +1. Select the drop-down arrow next to **New**. +2. Open the options menu |options-icon| next to the card template of your choosing. +3. Select **Set as default**. + +**Notes**: + +- The card template is applicable only to the board in which it’s created, and isn’t available in other boards within your team workspace. +- Comments on a template don't get populated on to new cards. +- Additionally, properties can't be hidden from a card template at this time. All cards on a board share the same properties, so adding or deleting a property on a template will also apply to all cards on a board. From 7226ed2cbba19ee9718f1dd3677bcab44d1db06f Mon Sep 17 00:00:00 2001 From: Asaad Mahmood Date: Mon, 25 Sep 2023 19:18:35 +0500 Subject: [PATCH 086/102] MM-54013- Removing some mattermost references (#4865) * MM-54013- Removing some mattermost references * Updating css * Updating logo * Removing clients banner from website * Update footer.html * Updating links and text * Updating image --- website/site/config.toml | 7 +- website/site/content/download/index.html | 2 +- website/site/content/feedback/_index.md | 2 - website/site/layouts/partials/footer.html | 191 ++---------------- website/site/layouts/partials/head.html | 2 +- website/site/layouts/partials/hero.html | 5 +- website/site/layouts/partials/intro.html | 31 +-- website/site/layouts/partials/nav.html | 4 +- website/site/static/css/partials/footer.css | 4 + website/site/static/css/partials/homepage.css | 2 +- website/site/static/img/logo-w-mattermost.svg | 15 ++ website/site/static/img/logo.svg | 18 +- website/site/static/img/templates/welcome.png | Bin 59247 -> 56560 bytes 13 files changed, 58 insertions(+), 225 deletions(-) create mode 100644 website/site/static/img/logo-w-mattermost.svg diff --git a/website/site/config.toml b/website/site/config.toml index 9fa615712..4ae332b17 100644 --- a/website/site/config.toml +++ b/website/site/config.toml @@ -65,7 +65,7 @@ pygmentsStyle = "manni" weight = 2 [[menu.postpend]] - url = "https://docs.mattermost.com/guides/boards.html" + url = "https://github.com/mattermost/focalboard/#readme" name = "Help Docs" weight = 3 @@ -74,11 +74,6 @@ pygmentsStyle = "manni" name = "Feedback" weight = 4 - [[menu.postpend]] - url = "https://mattermost.com/" - name = "Mattermost" - weight = 5 - # postpended links [[menu.postpend]] url = "/download" diff --git a/website/site/content/download/index.html b/website/site/content/download/index.html index 4ca628caa..aac91f477 100644 --- a/website/site/content/download/index.html +++ b/website/site/content/download/index.html @@ -12,7 +12,7 @@ weight: 0

For Teams

- Get started with Boards for free with Mattermost Cloud or install Mattermost as a self-hosted server. + Install the latest version of the Focalboard plugin in your existing Mattermost server

diff --git a/website/site/content/feedback/_index.md b/website/site/content/feedback/_index.md index 606606b7b..cfd2a3af4 100644 --- a/website/site/content/feedback/_index.md +++ b/website/site/content/feedback/_index.md @@ -8,8 +8,6 @@ weight: 1 Please contact us via one of the following: * [File a GitHub issue](https://github.com/mattermost/focalboard/issues) for bugs or feature ideas * [Start a GitHub discussion](https://github.com/mattermost/focalboard/discussions) -* [Mattermost community channel](https://community.mattermost.com/core/channels/focalboard) -* [Anonymous feedback form](https://docs.google.com/forms/d/e/1FAIpQLSdTq7M69Pdlz71CwucaSEG0FCK1M_WRvIbZbPr2imfT2QvUCQ/viewform?usp=sf_link) Focalboard is an open source project that is in early access. Help shape its future by sharing what you'd like to see with the community. diff --git a/website/site/layouts/partials/footer.html b/website/site/layouts/partials/footer.html index 514eac611..acee18166 100755 --- a/website/site/layouts/partials/footer.html +++ b/website/site/layouts/partials/footer.html @@ -1,184 +1,17 @@ -