1
0
mirror of https://github.com/mattermost/focalboard.git synced 2024-11-19 20:32:00 +02:00

[Refactor]: updated dependency for focalboard server (#5009)

* refactor: updated dependency for focalboard server

* chore: more dependency fixes

* refactor: removed the unless code

* refactor: added ctx for login and removed unnessary code

* refactor: bump up go version

* refactor: removed the commented code

* chore: upgraded golinter version

* fix: linter issue

* refactor: removed feature flg fix golinter

* refactor: removed feature flag from code

* revert: statistic and it's function

* refactor: removed ProductLimit related code

* refactor: removed isWithinViewsLimit implementation

* refactor: moved function GetUsedCardsCount to statistics.go from cloud.go

* refactor: removed insight code board

* refactor: removed limit dialog

* refactor: updated dependencies for linux

* chore: golinter fix

* chore: updated helper test function to use newLogger

* fix: go test

* refactor: db ping attempts from config

* revert: feature in action

* revert: feature flag in action

* revert: boardsEditor setting

---------

Co-authored-by: Rajat Dabade <rajat@Rajats-MacBook-Pro.local>
This commit is contained in:
Rajat Dabade 2024-06-07 23:30:08 +05:30 committed by GitHub
parent 7a31925d8a
commit c8e729b6fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
210 changed files with 1284 additions and 9864 deletions

View File

@ -33,7 +33,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19.5
go-version: 1.21
- name: "Test server: ${{matrix['db']}}"
run: cd focalboard; make server-test-${{matrix['db']}}
@ -53,7 +53,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19.5
go-version: 1.21
- name: Setup Node
uses: actions/setup-node@v3
@ -92,7 +92,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19.5
go-version: 1.21
- name: "Test server (minimum): ${{matrix['db']}}"
run: cd focalboard; make server-test-mini-${{matrix['db']}}
@ -114,7 +114,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19.5
go-version: 1.21
- name: "Test server (minimum): ${{matrix['db']}}"
run: cd focalboard; make server-test-mini-${{matrix['db']}}

View File

@ -38,7 +38,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19.5
go-version: 1.21
- name: Setup Node
uses: actions/setup-node@v3
@ -98,7 +98,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19.5
go-version: 1.21
- name: List Xcode versions
run: ls -n /Applications/ | grep Xcode*
@ -144,7 +144,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19.5
go-version: 1.21
- name: Setup NuGet
uses: nuget/setup-nuget@v1
@ -197,7 +197,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19.5
go-version: 1.21
- name: Set up Node
uses: actions/setup-node@v3

View File

@ -30,12 +30,12 @@ jobs:
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.19.5
go-version: 1.21
- uses: actions/checkout@v3
with:
path: "focalboard"
- 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
run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.59.0
- name: lint
run: |
cd focalboard

View File

@ -35,7 +35,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19.5
go-version: 1.21
- name: Setup Node
uses: actions/setup-node@v3
@ -96,7 +96,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19.5
go-version: 1.21
- name: List Xcode versions
run: ls -n /Applications/ | grep Xcode*
@ -143,7 +143,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19.5
go-version: 1.21
- name: Setup NuGet
uses: nuget/setup-nuget@v1
@ -197,7 +197,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19.5
go-version: 1.21
- name: Set up Node
uses: actions/setup-node@v3

View File

@ -3,6 +3,7 @@
"port": 8000,
"dbtype": "sqlite3",
"dbconfig": "./focalboard.db?_busy_timeout=5000",
"dbpingattempts": 5,
"dbtableprefix": "",
"postgres_dbconfig": "dbname=focalboard sslmode=disable",
"useSSL": false,

View File

@ -1,122 +1,118 @@
module github.com/mattermost/focalboard/linux
go 1.19
go 1.21
toolchain go1.21.8
replace github.com/mattermost/focalboard/server => ../server
require (
github.com/google/uuid v1.3.0
github.com/google/uuid v1.6.0
github.com/mattermost/focalboard/server v0.0.0-20230104182634-f909c2552e37
github.com/mattermost/mattermost-server/v6 v6.0.0-20230321114510-b61c096497ac
github.com/mattermost/mattermost/server/public v0.1.3
github.com/webview/webview v0.0.0-20220314230258-a2b7746141c3
)
require (
github.com/Masterminds/squirrel v1.5.3 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/Masterminds/squirrel v1.5.4 // 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.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/fatih/color v1.17.0 // indirect
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.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.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/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-hclog v1.6.3 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-plugin v1.6.1 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // 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.14 // indirect
github.com/klauspost/cpuid/v2 v2.2.3 // indirect
github.com/klauspost/compress v1.17.8 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // 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
github.com/lib/pq v1.10.7 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/magiconair/properties v1.8.7 // 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.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/mattermost/ldap v0.0.0-20231116144001-0f480c025956 // indirect
github.com/mattermost/logr/v2 v2.0.21 // indirect
github.com/mattermost/mattermost/server/v8 v8.0.0-20240529104128-9d30a62c9471 // indirect
github.com/mattermost/morph v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-isatty v0.0.20 // 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.45 // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/minio/minio-go/v7 v7.0.70 // 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
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
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/pelletier/go-toml/v2 v2.2.2 // 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-20220927061507-ef77025ab5aa // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/rs/xid v1.4.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.19.1 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.53.0 // indirect
github.com/prometheus/procfs v0.15.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rs/xid v1.5.0 // indirect
github.com/rudderlabs/analytics-go v3.3.3+incompatible // indirect
github.com/segmentio/backo-go v1.0.1 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/spf13/afero v1.8.2 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/segmentio/backo-go v1.1.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.10.1 // indirect
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.4 // indirect
github.com/spf13/viper v1.18.2 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.9.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tidwall/gjson v1.17.1 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tinylib/msgp v1.1.8 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/tinylib/msgp v1.1.9 // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/wiggin77/merror v1.0.4 // indirect
github.com/wiggin77/merror v1.0.5 // 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.5.0 // indirect
golang.org/x/mod v0.7.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sync v0.1.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
google.golang.org/protobuf v1.28.1 // indirect
github.com/yuin/goldmark v1.7.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/exp v0.0.0-20240529005216-23cca8864a10 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
google.golang.org/grpc v1.64.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // 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.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/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
modernc.org/libc v1.50.9 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
modernc.org/sqlite v1.29.10 // indirect
modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect
)

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@ import (
"github.com/mattermost/focalboard/server/services/permissions/localpermissions"
"github.com/webview/webview"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
var sessionToken string = "su-" + uuid.New().String()
@ -71,13 +71,13 @@ func runServer(port int) (*server.Server, error) {
permissionsService := localpermissions.New(db, logger)
params := server.Params{
Cfg: config,
SingleUserToken: sessionToken,
DBStore: db,
Logger: logger,
ServerID: "",
WSAdapter: nil,
NotifyBackends: nil,
Cfg: config,
SingleUserToken: sessionToken,
DBStore: db,
Logger: logger,
ServerID: "",
WSAdapter: nil,
NotifyBackends: nil,
PermissionsService: permissionsService,
}

View File

@ -31,10 +31,7 @@ linters:
enable:
- gofmt
- goimports
- deadcode
- ineffassign
- structcheck
- varcheck
- unparam
- errcheck
- govet
@ -48,13 +45,12 @@ linters:
- staticcheck
- prealloc
- asciicheck
- depguard
- dogsled
- dupl
- goconst
- gocritic
- godot
- goerr113
- err113
- goheader
- revive
- nakedret
@ -75,9 +71,7 @@ issues:
exclude-rules:
- path: server/manifest.go
linters:
- deadcode
- unused
- varcheck
- path: server/configuration.go
linters:
- unused

View File

@ -1,15 +1,35 @@
module github.com/mattermost/mattermost-plugin-starter-template/build
go 1.19
go 1.21
toolchain go1.21.8
require (
github.com/go-git/go-git/v5 v5.1.0
github.com/mattermost/mattermost-server/v6 v6.0.0-20220802151854-f07c31c5d933
github.com/mattermost/mattermost/server/public v0.1.3
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.7.2
github.com/stretchr/testify v1.8.4
sigs.k8s.io/yaml v1.2.0
)
require (
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-hclog v1.6.2 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-plugin v1.6.0 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/oklog/run v1.1.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/grpc v1.62.0 // indirect
google.golang.org/protobuf v1.32.0 // indirect
)
require (
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
@ -17,11 +37,11 @@ require (
github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a // indirect
github.com/emirpasic/gods v1.12.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
github.com/go-git/go-billy/v5 v5.0.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/graph-gophers/graphql-go v1.4.0 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
@ -30,8 +50,9 @@ require (
github.com/klauspost/compress v1.15.6 // indirect
github.com/klauspost/cpuid/v2 v2.0.13 // 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/ldap v0.0.0-20231116144001-0f480c025956 // indirect
github.com/mattermost/logr/v2 v2.0.21 // indirect
github.com/mattermost/mattermost/server/public v0.1.3
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/minio-go/v7 v7.0.28 // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
@ -40,23 +61,23 @@ require (
github.com/modern-go/reflect2 v1.0.2 // 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/pmezard/go-difflib v1.0.0 // indirect
github.com/rs/xid v1.4.0 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/tinylib/msgp v1.1.6 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/tinylib/msgp v1.1.9 // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/wiggin77/merror v1.0.3 // indirect
github.com/wiggin77/merror v1.0.5 // indirect
github.com/wiggin77/srslog v1.0.1 // indirect
github.com/xanzy/ssh-agent v0.2.1 // indirect
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/net v0.0.0-20220614195744-fb05da6f9022 // indirect
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/crypto v0.20.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/ini.v1 v1.66.6 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

View File

@ -18,6 +18,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@ -32,6 +34,9 @@ github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a h1:
github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a/go.mod h1:emQhSYTXqB0xxjLITTw4EaWZ+8IIQYw+kx9GqNUKdLg=
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
@ -43,6 +48,8 @@ github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aev
github.com/go-asn1-ber/asn1-ber v1.3.2-0.20191121212151-29be175fc3a3/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
@ -62,9 +69,13 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.5.5/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-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
@ -75,15 +86,29 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
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/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
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/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-hclog v1.6.2 h1:NOtoftovWkDheyUM/8JW3QMiXyxJK3uHRK7wV04nD2I=
github.com/hashicorp/go-hclog v1.6.2/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
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.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A=
github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI=
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
@ -116,10 +141,25 @@ 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/ldap v0.0.0-20231116144001-0f480c025956 h1:Y1Tu/swM31pVwwb2BTCsOdamENjjWCI6qmfHLbk6OZI=
github.com/mattermost/ldap v0.0.0-20231116144001-0f480c025956/go.mod h1:SRl30Lb7/QoYyohYeVBuqYvvmXSZJxZgiV3Zf6VbxjI=
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/logr/v2 v2.0.21 h1:CMHsP+nrbRlEC4g7BwOk1GAnMtHkniFhlSQPXy52be4=
github.com/mattermost/logr/v2 v2.0.21/go.mod h1:kZkB/zqKL9e+RY5gB3vGpsyenC+TpuiOenjMkvJJbzc=
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/public v0.1.3 h1:A3hQ3rNCwHfKAVxe7Hk3Zd9p2pyUKRmxtRPnkWP5SFM=
github.com/mattermost/mattermost/server/public v0.1.3/go.mod h1:PDPb/iqzJJ5ZvK/m70oDF55AXN/cOvVFj96Yu4e6j+Q=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
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-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/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
@ -130,6 +170,8 @@ github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
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.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -140,6 +182,8 @@ github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJE
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
@ -149,6 +193,8 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
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/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -188,6 +234,7 @@ github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYED
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
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.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -195,21 +242,29 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
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.9 h1:SHf3yoO2sGA0veCJeCBYLHuttAVFHGm2RHgNodW7wQU=
github.com/tinylib/msgp v1.1.9/go.mod h1:BCXGB54lDD8qUEPmiG0cQQUANC4IUQyB2ItS2UDlO/k=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
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.3 h1:8+ZHV+aSnJoYghE3EUThl15C6rvF2TYRSvOSBjdmNR8=
github.com/wiggin77/merror v1.0.3/go.mod h1:H2ETSu7/bPE0Ymf4bEwdUoo73OOEkdClnoRisfw0Nm0=
github.com/wiggin77/merror v1.0.5 h1:P+lzicsn4vPMycAf2mFf7Zk6G9eco5N+jB1qJ2XW3ME=
github.com/wiggin77/merror v1.0.5/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=
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
@ -230,6 +285,8 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
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.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg=
golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -250,6 +307,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
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=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -269,12 +328,22 @@ golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -283,6 +352,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
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/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -308,10 +379,18 @@ google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoA
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk=
google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
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.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
@ -321,6 +400,8 @@ gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI=
gopkg.in/ini.v1 v1.66.6/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=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -5,9 +5,8 @@ import (
"fmt"
"os"
"github.com/mattermost/mattermost/server/public/model"
"github.com/pkg/errors"
"github.com/mattermost/mattermost-server/v6/model"
)
const pluginIDGoFileTemplate = `// This file is automatically generated. Do not modify it manually.
@ -18,7 +17,7 @@ import (
"encoding/json"
"strings"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost/server/public/model"
)
var manifest *model.Manifest

View File

@ -2,13 +2,14 @@
package main
import (
"context"
"errors"
"fmt"
"log"
"net"
"os"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost/server/public/model"
)
const helpText = `
@ -91,7 +92,8 @@ func getClient() (*model.Client4, error) {
if adminUsername != "" && adminPassword != "" {
client := model.NewAPIv4Client(siteURL)
log.Printf("Authenticating as %s against %s.", adminUsername, siteURL)
_, _, err := client.Login(adminUsername, adminPassword)
ctx := context.Background()
_, _, err := client.Login(ctx, adminUsername, adminPassword)
if err != nil {
return nil, fmt.Errorf("failed to login as %s: %w", adminUsername, err)
}
@ -119,14 +121,16 @@ func deploy(client *model.Client4, pluginID, bundlePath string) error {
}
defer pluginBundle.Close()
ctx := context.Background()
log.Print("Uploading plugin via API.")
_, _, err = client.UploadPluginForced(pluginBundle)
_, _, err = client.UploadPluginForced(ctx, pluginBundle)
if err != nil {
return fmt.Errorf("failed to upload plugin bundle: %s", err)
}
log.Print("Enabling plugin.")
_, err = client.EnablePlugin(pluginID)
_, err = client.EnablePlugin(ctx, pluginID)
if err != nil {
return fmt.Errorf("failed to enable plugin: %s", err)
}
@ -136,8 +140,10 @@ func deploy(client *model.Client4, pluginID, bundlePath string) error {
// disablePlugin attempts to disable the plugin via the Client4 API.
func disablePlugin(client *model.Client4, pluginID string) error {
ctx := context.Background()
log.Print("Disabling plugin.")
_, err := client.DisablePlugin(pluginID)
_, err := client.DisablePlugin(ctx, pluginID)
if err != nil {
return fmt.Errorf("failed to disable plugin: %w", err)
}
@ -147,8 +153,10 @@ func disablePlugin(client *model.Client4, pluginID string) error {
// enablePlugin attempts to enable the plugin via the Client4 API.
func enablePlugin(client *model.Client4, pluginID string) error {
ctx := context.Background()
log.Print("Enabling plugin.")
_, err := client.EnablePlugin(pluginID)
_, err := client.EnablePlugin(ctx, pluginID)
if err != nil {
return fmt.Errorf("failed to enable plugin: %w", err)
}

View File

@ -1,123 +1,121 @@
module github.com/mattermost/focalboard/mattermost-plugin
go 1.19
go 1.21
toolchain go1.21.8
require (
github.com/golang/mock v1.6.0
github.com/gorilla/mux v1.8.0
github.com/gorilla/mux v1.8.1
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
github.com/mattermost/mattermost/server/public v0.1.3
github.com/stretchr/testify v1.9.0
)
require (
github.com/BurntSushi/toml v1.2.0 // indirect
github.com/Masterminds/squirrel v1.5.3 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/mattermost/mattermost/server/v8 v8.0.0-20240529104128-9d30a62c9471 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20240529005216-23cca8864a10 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
)
require (
github.com/Masterminds/squirrel v1.5.4 // 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.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/fatih/color v1.17.0 // indirect
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.7.0 // indirect
github.com/golang-migrate/migrate/v4 v4.15.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // 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/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/hashicorp/go-hclog v1.6.3 // indirect
github.com/hashicorp/go-plugin v1.6.1 // 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.14 // indirect
github.com/klauspost/cpuid/v2 v2.2.3 // indirect
github.com/klauspost/compress v1.17.8 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // 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
github.com/lib/pq v1.10.7 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/magiconair/properties v1.8.7 // 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.16 // indirect
github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e // indirect
github.com/mattermost/squirrel v0.2.0 // indirect
github.com/mattermost/ldap v0.0.0-20231116144001-0f480c025956 // indirect
github.com/mattermost/logr/v2 v2.0.21 // indirect
github.com/mattermost/morph v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-isatty v0.0.20 // 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.45 // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/minio/minio-go/v7 v7.0.70 // 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
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
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.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-20220927061507-ef77025ab5aa // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/rs/xid v1.4.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.19.1 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.53.0 // indirect
github.com/prometheus/procfs v0.15.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rs/xid v1.5.0 // indirect
github.com/rudderlabs/analytics-go v3.3.3+incompatible // indirect
github.com/segmentio/backo-go v1.0.1 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/spf13/afero v1.8.2 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/segmentio/backo-go v1.1.0 // indirect
github.com/sergi/go-diff v1.3.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
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.4 // indirect
github.com/spf13/viper v1.18.2 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tidwall/gjson v1.17.1 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tinylib/msgp v1.1.8 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/tinylib/msgp v1.1.9 // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/wiggin77/merror v1.0.4 // indirect
github.com/wiggin77/merror v1.0.5 // 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.5.0 // indirect
golang.org/x/mod v0.7.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sync v0.1.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
google.golang.org/protobuf v1.28.1 // indirect
github.com/yuin/goldmark v1.7.1 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
google.golang.org/grpc v1.64.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // 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.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/libc v1.50.9 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
modernc.org/sqlite v1.29.10 // indirect
modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect
)

File diff suppressed because it is too large Load Diff

View File

@ -9,10 +9,10 @@ import (
"github.com/gorilla/mux"
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/mattermost-server/v6/plugin"
"github.com/mattermost/mattermost/server/public/plugin"
mm_model "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
mm_model "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
type storeService interface {
@ -180,14 +180,6 @@ func (a *pluginAPIAdapter) PublishPluginClusterEvent(ev mm_model.PluginClusterEv
return a.api.PublishPluginClusterEvent(ev, opts)
}
//
// Cloud service.
//
func (a *pluginAPIAdapter) GetCloudLimits() (*mm_model.ProductLimits, error) {
return a.api.GetCloudLimits()
}
//
// Config service.
//

View File

@ -1,84 +0,0 @@
package boards
import (
"github.com/mattermost/focalboard/server/app"
"github.com/mattermost/focalboard/server/model"
mm_model "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/product"
)
// boardsServiceAPI provides a service API for other products such as Channels.
type boardsServiceAPI struct {
app *app.App
}
func NewBoardsServiceAPI(app *BoardsApp) *boardsServiceAPI {
return &boardsServiceAPI{
app: app.server.App(),
}
}
func (bs *boardsServiceAPI) GetTemplates(teamID string, userID string) ([]*model.Board, error) {
return bs.app.GetTemplateBoards(teamID, userID)
}
func (bs *boardsServiceAPI) GetBoard(boardID string) (*model.Board, error) {
return bs.app.GetBoard(boardID)
}
func (bs *boardsServiceAPI) CreateBoard(board *model.Board, userID string, addmember bool) (*model.Board, error) {
return bs.app.CreateBoard(board, userID, addmember)
}
func (bs *boardsServiceAPI) PatchBoard(boardPatch *model.BoardPatch, boardID string, userID string) (*model.Board, error) {
return bs.app.PatchBoard(boardPatch, boardID, userID)
}
func (bs *boardsServiceAPI) DeleteBoard(boardID string, userID string) error {
return bs.app.DeleteBoard(boardID, userID)
}
func (bs *boardsServiceAPI) SearchBoards(searchTerm string, searchField model.BoardSearchField,
userID string, includePublicBoards bool) ([]*model.Board, error) {
return bs.app.SearchBoardsForUser(searchTerm, searchField, userID, includePublicBoards)
}
func (bs *boardsServiceAPI) LinkBoardToChannel(boardID string, channelID string, userID string) (*model.Board, error) {
patch := &model.BoardPatch{
ChannelID: &channelID,
}
return bs.app.PatchBoard(patch, boardID, userID)
}
func (bs *boardsServiceAPI) GetCards(boardID string) ([]*model.Card, error) {
return bs.app.GetCardsForBoard(boardID, 0, 0)
}
func (bs *boardsServiceAPI) GetCard(cardID string) (*model.Card, error) {
return bs.app.GetCardByID(cardID)
}
func (bs *boardsServiceAPI) CreateCard(card *model.Card, boardID string, userID string) (*model.Card, error) {
return bs.app.CreateCard(card, boardID, userID, false)
}
func (bs *boardsServiceAPI) PatchCard(cardPatch *model.CardPatch, cardID string, userID string) (*model.Card, error) {
return bs.app.PatchCard(cardPatch, cardID, userID, false)
}
func (bs *boardsServiceAPI) DeleteCard(cardID string, userID string) error {
return bs.app.DeleteBlock(cardID, userID)
}
func (bs *boardsServiceAPI) HasPermissionToBoard(userID, boardID string, permission *mm_model.Permission) bool {
return bs.app.HasPermissionToBoard(userID, boardID, permission)
}
func (bs *boardsServiceAPI) DuplicateBoard(boardID string, userID string,
toTeam string, asTemplate bool) (*model.BoardsAndBlocks, []*model.BoardMember, error) {
return bs.app.DuplicateBoard(boardID, userID, toTeam, asTemplate)
}
// Ensure boardsServiceAPI implements product.BoardsService interface.
var _ product.BoardsService = (*boardsServiceAPI)(nil)

View File

@ -17,12 +17,11 @@ import (
"github.com/mattermost/focalboard/server/services/store/mattermostauthlayer"
"github.com/mattermost/focalboard/server/services/store/sqlstore"
"github.com/mattermost/focalboard/server/ws"
"github.com/mattermost/mattermost/server/public/pluginapi/cluster"
mm_model "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/plugin"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-plugin-api/cluster"
mm_model "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/plugin"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
const (
@ -214,12 +213,6 @@ func (b *BoardsApp) OnPluginClusterEvent(_ *plugin.Context, ev mm_model.PluginCl
b.wsPluginAdapter.HandleClusterEvent(ev)
}
func (b *BoardsApp) OnCloudLimitsUpdated(limits *mm_model.ProductLimits) {
if err := b.server.App().SetCloudLimits(limits); err != nil {
b.logger.Error("Error setting the cloud limits for Boards", mlog.Err(err))
}
}
// ServeHTTP demonstrates a plugin that handles HTTP requests by greeting the world.
func (b *BoardsApp) ServeHTTP(_ *plugin.Context, w http.ResponseWriter, r *http.Request) {
router := b.server.GetRootRouter()

View File

@ -11,8 +11,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func TestSetConfiguration(t *testing.T) {
@ -62,6 +62,20 @@ func TestSetConfiguration(t *testing.T) {
PrivacySettings: *basePrivacySettings,
}
t.Run("test boards feature flags", func(t *testing.T) {
featureFlags := &model.FeatureFlags{
TestFeature: "test",
TestBoolFeature: boolTrue,
}
mmConfig := baseConfig
mmConfig.FeatureFlags = featureFlags
config := createBoardsConfig(*mmConfig, "", "")
assert.Equal(t, "true", config.FeatureFlags["TestBoolFeature"])
assert.Equal(t, "test", config.FeatureFlags["TestFeature"])
})
t.Run("test enable telemetry", func(t *testing.T) {
logSettings := &model.LogSettings{
EnableDiagnostics: &boolTrue,
@ -82,24 +96,6 @@ func TestSetConfiguration(t *testing.T) {
config := createBoardsConfig(*mmConfig, "", "")
assert.Equal(t, true, config.EnablePublicSharedBoards)
})
t.Run("test boards feature flags", func(t *testing.T) {
featureFlags := &model.FeatureFlags{
TestFeature: "test",
TestBoolFeature: boolTrue,
BoardsFeatureFlags: "hello_world-myTest",
}
mmConfig := baseConfig
mmConfig.FeatureFlags = featureFlags
config := createBoardsConfig(*mmConfig, "", "")
assert.Equal(t, "true", config.FeatureFlags["TestBoolFeature"])
assert.Equal(t, "test", config.FeatureFlags["TestFeature"])
assert.Equal(t, "true", config.FeatureFlags["hello_world"])
assert.Equal(t, "true", config.FeatureFlags["myTest"])
})
}
func TestServeHTTP(t *testing.T) {
@ -108,7 +104,7 @@ func TestServeHTTP(t *testing.T) {
b := &BoardsApp{
server: th.Server,
logger: mlog.CreateConsoleTestLogger(true, mlog.LvlError),
logger: mlog.CreateConsoleTestLogger(t),
}
assert := assert.New(t)

View File

@ -10,7 +10,7 @@ import (
"github.com/mattermost/focalboard/server/services/config"
mm_model "github.com/mattermost/mattermost-server/v6/model"
mm_model "github.com/mattermost/mattermost/server/public/model"
)
const defaultS3Timeout = 60 * 1000 // 60 seconds
@ -81,9 +81,7 @@ func createBoardsConfig(mmconfig mm_model.Config, baseURL string, serverID strin
}
serverRoot := baseURL + "/plugins/focalboard"
if mmconfig.FeatureFlags.BoardsProduct {
serverRoot = baseURL + "/boards"
}
return &config.Configuration{
ServerRoot: serverRoot,
Port: -1,
@ -118,6 +116,21 @@ func createBoardsConfig(mmconfig mm_model.Config, baseURL string, serverID strin
}
}
func parseFeatureFlags(configFeatureFlags map[string]string) map[string]string {
featureFlags := make(map[string]string)
for key, value := range configFeatureFlags {
// Break out FeatureFlags and pass remaining
if key == boardsFeatureFlagName {
for _, flag := range strings.Split(value, "-") {
featureFlags[flag] = "true"
}
} else {
featureFlags[key] = value
}
}
return featureFlags
}
func getPluginSetting(mmConfig mm_model.Config, key string) (interface{}, bool) {
plugin, ok := mmConfig.PluginSettings.Plugins[PluginName]
if !ok {
@ -142,18 +155,3 @@ func getPluginSettingInt(mmConfig mm_model.Config, key string, def int) int {
}
return int(math.Round(valFloat))
}
func parseFeatureFlags(configFeatureFlags map[string]string) map[string]string {
featureFlags := make(map[string]string)
for key, value := range configFeatureFlags {
// Break out FeatureFlags and pass remaining
if key == boardsFeatureFlagName {
for _, flag := range strings.Split(value, "-") {
featureFlags[flag] = "true"
}
} else {
featureFlags[key] = value
}
}
return featureFlags
}

View File

@ -75,23 +75,17 @@ func (b *BoardsApp) OnConfigurationChange() error {
}
mmconfig := b.servicesAPI.GetConfig()
// handle plugin configuration settings
enableShareBoards := false
if mmconfig.PluginSettings.Plugins[PluginName][SharedBoardsName] == true {
enableShareBoards = true
}
if mmconfig.ProductSettings.EnablePublicSharedBoards != nil {
enableShareBoards = *mmconfig.ProductSettings.EnablePublicSharedBoards
}
configuration := &configuration{
EnablePublicSharedBoards: enableShareBoards,
}
b.setConfiguration(configuration)
b.server.Config().EnablePublicSharedBoards = enableShareBoards
// handle feature flags
b.server.Config().FeatureFlags = parseFeatureFlags(mmconfig.FeatureFlags.ToMap())
// handle Data Retention settings
enableBoardsDeletion := false
if mmconfig.DataRetentionSettings.EnableBoardsDeletion != nil {

View File

@ -14,8 +14,8 @@ import (
mockservicesapi "github.com/mattermost/focalboard/server/model/mocks"
serverModel "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
serverModel "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -54,9 +54,6 @@ func TestOnConfigurationChange(t *testing.T) {
basePlugins[PluginName] = make(map[string]interface{})
basePlugins[PluginName][SharedBoardsName] = true
baseFeatureFlags := &serverModel.FeatureFlags{
BoardsFeatureFlags: "Feature1-Feature2",
}
basePluginSettings := &serverModel.PluginSettings{
Directory: &stringRef,
Plugins: basePlugins,
@ -77,7 +74,6 @@ func TestOnConfigurationChange(t *testing.T) {
}
baseConfig := &serverModel.Config{
FeatureFlags: baseFeatureFlags,
PluginSettings: *basePluginSettings,
DataRetentionSettings: *baseDataRetentionSettings,
TeamSettings: *baseTeamSettings,
@ -96,7 +92,7 @@ func TestOnConfigurationChange(t *testing.T) {
server: th.Server,
wsPluginAdapter: &FakePluginAdapter{},
servicesAPI: api,
logger: mlog.CreateConsoleTestLogger(true, mlog.LvlError),
logger: mlog.CreateConsoleTestLogger(&testing.T{}),
}
err := b.OnConfigurationChange()
@ -106,10 +102,6 @@ func TestOnConfigurationChange(t *testing.T) {
// make sure both App and Server got updated
assert.True(t, b.server.Config().EnablePublicSharedBoards)
assert.True(t, b.server.App().GetClientConfig().EnablePublicSharedBoards)
assert.Equal(t, "true", b.server.Config().FeatureFlags["Feature1"])
assert.Equal(t, "true", b.server.Config().FeatureFlags["Feature2"])
assert.Equal(t, "", b.server.Config().FeatureFlags["Feature3"])
})
}

View File

@ -15,8 +15,8 @@ import (
"github.com/mattermost/focalboard/server/services/store/mockstore"
"github.com/stretchr/testify/assert"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
type TestHelperMockStore struct {
@ -53,7 +53,7 @@ func newTestServerMock(mockStore *mockstore.MockStore) *server.Server {
WebPath: "/",
}
logger := mlog.CreateConsoleTestLogger(true, mlog.LvlDebug)
logger, _ := mlog.NewLogger()
mockStore.EXPECT().GetTeam(gomock.Any()).Return(nil, nil).AnyTimes()
mockStore.EXPECT().UpsertTeamSignupToken(gomock.Any()).AnyTimes()
@ -79,9 +79,10 @@ func TestRunDataRetention(t *testing.T) {
th, tearDown := SetupTestHelperMockStore(t)
defer tearDown()
logger, _ := mlog.NewLogger()
b := &BoardsApp{
server: th.Server,
logger: mlog.CreateConsoleTestLogger(true, mlog.LvlError),
logger: logger,
}
now := time.Now().UnixNano()

View File

@ -7,8 +7,8 @@ import (
"errors"
"net/http"
mm_model "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
mm_model "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/mattermost/focalboard/server/model"
)

View File

@ -12,7 +12,7 @@ import (
"github.com/mattermost/focalboard/server/services/permissions"
"github.com/mattermost/focalboard/server/services/store"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
type notifyBackendParams struct {

View File

@ -9,8 +9,8 @@ import (
"net/url"
"strings"
mm_model "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/markdown"
mm_model "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/markdown"
)
func postWithBoardsEmbed(post *mm_model.Post) *mm_model.Post {

View File

@ -5,9 +5,9 @@ import (
"encoding/json"
"fmt"
pluginapi "github.com/mattermost/mattermost-plugin-api"
pluginapi "github.com/mattermost/mattermost/server/public/pluginapi"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
const (

View File

@ -1,7 +1,7 @@
package main
import (
"github.com/mattermost/mattermost-server/v6/plugin"
"github.com/mattermost/mattermost/server/public/plugin"
)
func main() {

View File

@ -6,7 +6,7 @@ import (
"encoding/json"
"strings"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost/server/public/model"
)
var manifest *model.Manifest

View File

@ -11,11 +11,11 @@ import (
"github.com/mattermost/focalboard/mattermost-plugin/server/boards"
"github.com/mattermost/focalboard/server/model"
pluginapi "github.com/mattermost/mattermost-plugin-api"
pluginapi "github.com/mattermost/mattermost/server/public/pluginapi"
mm_model "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/plugin"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
mm_model "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/plugin"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
var ErrPluginNotAllowed = errors.New("boards plugin not allowed while Boards product enabled")
@ -23,16 +23,10 @@ var ErrPluginNotAllowed = errors.New("boards plugin not allowed while Boards pro
// Plugin implements the interface expected by the Mattermost server to communicate between the server and plugin processes.
type Plugin struct {
plugin.MattermostPlugin
boardsApp *boards.BoardsApp
}
func (p *Plugin) OnActivate() error {
if p.API.GetConfig().FeatureFlags.BoardsProduct {
p.API.LogError(ErrPluginNotAllowed.Error())
return ErrPluginNotAllowed
}
client := pluginapi.NewClient(p.API, p.Driver)
logger, _ := mlog.NewLogger()
@ -97,10 +91,6 @@ func (p *Plugin) MessageWillBeUpdated(ctx *plugin.Context, newPost, oldPost *mm_
return p.boardsApp.MessageWillBeUpdated(ctx, newPost, oldPost)
}
func (p *Plugin) OnCloudLimitsUpdated(limits *mm_model.ProductLimits) {
p.boardsApp.OnCloudLimitsUpdated(limits)
}
func (p *Plugin) RunDataRetention(nowTime, batchSize int64) (int64, error) {
return p.boardsApp.RunDataRetention(nowTime, batchSize)
}

View File

@ -38,7 +38,6 @@ import '../../../webapp/src/styles/focalboard-variables.scss'
import '../../../webapp/src/styles/main.scss'
import '../../../webapp/src/styles/labels.scss'
import octoClient from '../../../webapp/src/octoClient'
import {Constants} from '../../../webapp/src/constants'
import {Board} from '../../../webapp/src/blocks/board'
import appBarIcon from '../../../webapp/static/app-bar-icon.png'
@ -368,21 +367,6 @@ export default class Plugin {
false
)
// Insights handler
if (this.registry?.registerInsightsHandler) {
this.registry?.registerInsightsHandler(async (timeRange: string, page: number, perPage: number, teamId: string, insightType: string) => {
if (insightType === Constants.myInsights) {
const data = await octoClient.getMyTopBoards(timeRange, page, perPage, teamId)
return data
}
const data = await octoClient.getTeamTopBoards(timeRange, page, perPage, teamId)
return data
})
}
// Site statistics handler
if (registry.registerSiteStatisticsHandler) {
registry.registerSiteStatisticsHandler(async () => {

View File

@ -41,13 +41,12 @@ linters:
- staticcheck
- prealloc
- asciicheck
- depguard
- dogsled
- dupl
- goconst
- gocritic
- godot
- goerr113
- err113
- goheader
- revive
- nakedret

View File

@ -10,7 +10,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/audit"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
type AdminSetPasswordData struct {

View File

@ -13,7 +13,7 @@ import (
"github.com/mattermost/focalboard/server/services/audit"
"github.com/mattermost/focalboard/server/services/permissions"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
const (
@ -85,8 +85,6 @@ func (a *API) RegisterRoutes(r *mux.Router) {
a.registerAchivesRoutes(apiv2)
a.registerSubscriptionsRoutes(apiv2)
a.registerFilesRoutes(apiv2)
a.registerLimitsRoutes(apiv2)
a.registerInsightsRoutes(apiv2)
a.registerOnboardingRoutes(apiv2)
a.registerSearchRoutes(apiv2)
a.registerConfigRoutes(apiv2)

View File

@ -9,14 +9,14 @@ import (
"testing"
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/stretchr/testify/require"
pluginapi "github.com/mattermost/mattermost-plugin-api"
pluginapi "github.com/mattermost/mattermost/server/public/pluginapi"
)
func TestErrorResponse(t *testing.T) {
testAPI := API{logger: mlog.CreateConsoleTestLogger(false, mlog.LvlDebug)}
testAPI := API{logger: mlog.CreateConsoleTestLogger(t)}
testCases := []struct {
Name string

View File

@ -9,8 +9,8 @@ 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"
mmModel "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
const (

View File

@ -14,7 +14,7 @@ import (
"github.com/mattermost/focalboard/server/services/auth"
"github.com/mattermost/focalboard/server/utils"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func (a *API) registerAuthRoutes(r *mux.Router) {

View File

@ -11,7 +11,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/audit"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func (a *API) registerBlocksRoutes(r *mux.Router) {
@ -159,13 +159,6 @@ func (a *API) handleGetBlocks(w http.ResponseWriter, r *http.Request) {
mlog.Int("block_count", len(blocks)),
)
var bErr error
blocks, bErr = a.app.ApplyCloudLimits(blocks)
if bErr != nil {
a.errorResponse(w, r, err)
return
}
json, err := json.Marshal(blocks)
if err != nil {
a.errorResponse(w, r, err)

View File

@ -9,7 +9,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/audit"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func (a *API) registerBoardsRoutes(r *mux.Router) {

View File

@ -10,7 +10,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/audit"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func (a *API) registerBoardsAndBlocksRoutes(r *mux.Router) {

View File

@ -11,7 +11,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/audit"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
const (

View File

@ -9,8 +9,8 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/audit"
mm_model "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
mm_model "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func (a *API) registerChannelsRoutes(r *mux.Router) {

View File

@ -9,8 +9,8 @@ import (
"github.com/gorilla/mux"
"github.com/mattermost/focalboard/server/model"
mm_model "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
mm_model "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
const (

View File

@ -20,9 +20,9 @@ import (
"github.com/mattermost/focalboard/server/services/audit"
mmModel "github.com/mattermost/mattermost-server/v6/model"
mmModel "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
var UnsafeContentTypes = [...]string{

View File

@ -1,258 +0,0 @@
package api
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"time"
"github.com/gorilla/mux"
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/audit"
mmModel "github.com/mattermost/mattermost-server/v6/model"
)
func (a *API) registerInsightsRoutes(r *mux.Router) {
// Insights APIs
r.HandleFunc("/teams/{teamID}/boards/insights", a.sessionRequired(a.handleTeamBoardsInsights)).Methods("GET")
r.HandleFunc("/users/me/boards/insights", a.sessionRequired(a.handleUserBoardsInsights)).Methods("GET")
}
func (a *API) handleTeamBoardsInsights(w http.ResponseWriter, r *http.Request) {
// swagger:operation GET /teams/{teamID}/boards/insights handleTeamBoardsInsights
//
// Returns team boards insights
//
// ---
// produces:
// - application/json
// parameters:
// - name: teamID
// in: path
// description: Team ID
// required: true
// type: string
// - name: time_range
// in: query
// description: duration of data to calculate insights for
// required: true
// type: string
// - name: page
// in: query
// description: page offset for top boards
// required: true
// type: string
// - name: per_page
// in: query
// description: limit for boards in a page.
// required: true
// type: string
// security:
// - BearerAuth: []
// responses:
// '200':
// description: success
// schema:
// type: array
// items:
// "$ref": "#/definitions/BoardInsight"
// default:
// description: internal error
// schema:
// "$ref": "#/definitions/ErrorResponse"
if !a.MattermostAuth {
a.errorResponse(w, r, model.NewErrNotImplemented("not permitted in standalone mode"))
return
}
vars := mux.Vars(r)
teamID := vars["teamID"]
userID := getUserID(r)
query := r.URL.Query()
timeRange := query.Get("time_range")
if !a.permissions.HasPermissionToTeam(userID, teamID, model.PermissionViewTeam) {
a.errorResponse(w, r, model.NewErrPermission("access denied to team"))
return
}
auditRec := a.makeAuditRecord(r, "getTeamBoardsInsights", audit.Fail)
defer a.audit.LogRecord(audit.LevelRead, auditRec)
page, err := strconv.Atoi(query.Get("page"))
if err != nil {
message := fmt.Sprintf("error converting page parameter to integer: %s", err)
a.errorResponse(w, r, model.NewErrBadRequest(message))
return
}
if page < 0 {
a.errorResponse(w, r, model.NewErrBadRequest("Invalid page parameter"))
}
perPage, err := strconv.Atoi(query.Get("per_page"))
if err != nil {
message := fmt.Sprintf("error converting per_page parameter to integer: %s", err)
a.errorResponse(w, r, model.NewErrBadRequest(message))
return
}
if perPage < 0 {
a.errorResponse(w, r, model.NewErrBadRequest("Invalid page parameter"))
}
userTimezone, aErr := a.app.GetUserTimezone(userID)
if aErr != nil {
message := fmt.Sprintf("Error getting time zone of user: %s", aErr)
a.errorResponse(w, r, model.NewErrBadRequest(message))
return
}
userLocation, _ := time.LoadLocation(userTimezone)
if userLocation == nil {
userLocation = time.Now().UTC().Location()
}
// get unix time for duration
startTime, appErr := mmModel.GetStartOfDayForTimeRange(timeRange, userLocation)
if appErr != nil {
a.errorResponse(w, r, model.NewErrBadRequest(appErr.Message))
return
}
boardsInsights, err := a.app.GetTeamBoardsInsights(userID, teamID, &mmModel.InsightsOpts{
StartUnixMilli: mmModel.GetMillisForTime(*startTime),
Page: page,
PerPage: perPage,
})
if err != nil {
a.errorResponse(w, r, err)
return
}
data, err := json.Marshal(boardsInsights)
if err != nil {
a.errorResponse(w, r, err)
return
}
jsonBytesResponse(w, http.StatusOK, data)
auditRec.AddMeta("teamBoardsInsightCount", len(boardsInsights.Items))
auditRec.Success()
}
func (a *API) handleUserBoardsInsights(w http.ResponseWriter, r *http.Request) {
// swagger:operation GET /users/me/boards/insights getUserBoardsInsights
//
// Returns user boards insights
//
// ---
// produces:
// - application/json
// parameters:
// - name: teamID
// in: path
// description: Team ID
// required: true
// type: string
// - name: time_range
// in: query
// description: duration of data to calculate insights for
// required: true
// type: string
// - name: page
// in: query
// description: page offset for top boards
// required: true
// type: string
// - name: per_page
// in: query
// description: limit for boards in a page.
// required: true
// type: string
// security:
// - BearerAuth: []
// responses:
// '200':
// description: success
// schema:
// type: array
// items:
// "$ref": "#/definitions/BoardInsight"
// default:
// description: internal error
// schema:
// "$ref": "#/definitions/ErrorResponse"
if !a.MattermostAuth {
a.errorResponse(w, r, model.NewErrNotImplemented("not permitted in standalone mode"))
return
}
userID := getUserID(r)
query := r.URL.Query()
teamID := query.Get("team_id")
timeRange := query.Get("time_range")
if !a.permissions.HasPermissionToTeam(userID, teamID, model.PermissionViewTeam) {
a.errorResponse(w, r, model.NewErrPermission("access denied to team"))
return
}
auditRec := a.makeAuditRecord(r, "getUserBoardsInsights", audit.Fail)
defer a.audit.LogRecord(audit.LevelRead, auditRec)
page, err := strconv.Atoi(query.Get("page"))
if err != nil {
a.errorResponse(w, r, model.NewErrBadRequest("error converting page parameter to integer"))
return
}
if page < 0 {
a.errorResponse(w, r, model.NewErrBadRequest("Invalid page parameter"))
}
perPage, err := strconv.Atoi(query.Get("per_page"))
if err != nil {
message := fmt.Sprintf("error converting per_page parameter to integer: %s", err)
a.errorResponse(w, r, model.NewErrBadRequest(message))
return
}
if perPage < 0 {
a.errorResponse(w, r, model.NewErrBadRequest("Invalid page parameter"))
}
userTimezone, aErr := a.app.GetUserTimezone(userID)
if aErr != nil {
message := fmt.Sprintf("Error getting time zone of user: %s", aErr)
a.errorResponse(w, r, model.NewErrBadRequest(message))
return
}
userLocation, _ := time.LoadLocation(userTimezone)
if userLocation == nil {
userLocation = time.Now().UTC().Location()
}
// get unix time for duration
startTime, appErr := mmModel.GetStartOfDayForTimeRange(timeRange, userLocation)
if appErr != nil {
a.errorResponse(w, r, model.NewErrBadRequest(appErr.Message))
return
}
boardsInsights, err := a.app.GetUserBoardsInsights(userID, teamID, &mmModel.InsightsOpts{
StartUnixMilli: mmModel.GetMillisForTime(*startTime),
Page: page,
PerPage: perPage,
})
if err != nil {
a.errorResponse(w, r, err)
return
}
data, err := json.Marshal(boardsInsights)
if err != nil {
a.errorResponse(w, r, err)
return
}
jsonBytesResponse(w, http.StatusOK, data)
auditRec.AddMeta("userBoardInsightCount", len(boardsInsights.Items))
auditRec.Success()
}

View File

@ -1,87 +0,0 @@
package api
import (
"encoding/json"
"net/http"
"github.com/gorilla/mux"
"github.com/mattermost/focalboard/server/model"
)
func (a *API) registerLimitsRoutes(r *mux.Router) {
// limits
r.HandleFunc("/limits", a.sessionRequired(a.handleCloudLimits)).Methods("GET")
r.HandleFunc("/teams/{teamID}/notifyadminupgrade", a.sessionRequired(a.handleNotifyAdminUpgrade)).Methods(http.MethodPost)
}
func (a *API) handleCloudLimits(w http.ResponseWriter, r *http.Request) {
// swagger:operation GET /limits cloudLimits
//
// Fetches the cloud limits of the server.
//
// ---
// produces:
// - application/json
// security:
// - BearerAuth: []
// responses:
// '200':
// description: success
// schema:
// "$ref": "#/definitions/BoardsCloudLimits"
// default:
// description: internal error
// schema:
// "$ref": "#/definitions/ErrorResponse"
boardsCloudLimits, err := a.app.GetBoardsCloudLimits()
if err != nil {
a.errorResponse(w, r, err)
return
}
data, err := json.Marshal(boardsCloudLimits)
if err != nil {
a.errorResponse(w, r, err)
return
}
jsonBytesResponse(w, http.StatusOK, data)
}
func (a *API) handleNotifyAdminUpgrade(w http.ResponseWriter, r *http.Request) {
// swagger:operation GET /api/v2/teams/{teamID}/notifyadminupgrade handleNotifyAdminUpgrade
//
// Notifies admins for upgrade request.
//
// ---
// produces:
// - application/json
// parameters:
// - name: teamID
// in: path
// description: Team ID
// required: true
// type: string
// security:
// - BearerAuth: []
// responses:
// '200':
// description: success
// default:
// description: internal error
// schema:
// "$ref": "#/definitions/ErrorResponse"
if !a.MattermostAuth {
a.errorResponse(w, r, model.NewErrNotImplemented("not permitted in standalone mode"))
return
}
vars := mux.Vars(r)
teamID := vars["teamID"]
if err := a.app.NotifyPortalAdminsUpgradeRequest(teamID); err != nil {
jsonStringResponse(w, http.StatusOK, "{}")
}
}

View File

@ -8,7 +8,7 @@ import (
"github.com/gorilla/mux"
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/audit"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func (a *API) registerMembersRoutes(r *mux.Router) {

View File

@ -8,7 +8,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/audit"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func (a *API) registerSearchRoutes(r *mux.Router) {

View File

@ -10,7 +10,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/audit"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
var ErrTurningOnSharing = errors.New("turning on sharing for board failed, see log for details")

View File

@ -6,7 +6,7 @@ import (
"github.com/gorilla/mux"
"github.com/mattermost/focalboard/server/model"
mmModel "github.com/mattermost/mattermost-server/v6/model"
mmModel "github.com/mattermost/mattermost/server/public/model"
)
func (a *API) registerStatisticsRoutes(r *mux.Router) {

View File

@ -10,7 +10,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/audit"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func (a *API) registerSubscriptionsRoutes(r *mux.Router) {

View File

@ -9,11 +9,11 @@ import (
"github.com/mattermost/focalboard/server/app"
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func TestHello(t *testing.T) {
testAPI := API{logger: mlog.CreateConsoleTestLogger(false, mlog.LvlDebug)}
testAPI := API{logger: mlog.CreateConsoleTestLogger(t)}
t.Run("Returns 'Hello' on success", func(t *testing.T) {
request, _ := http.NewRequest(http.MethodGet, "/hello", nil)
@ -35,7 +35,7 @@ func TestHello(t *testing.T) {
}
func TestPing(t *testing.T) {
testAPI := API{logger: mlog.CreateConsoleTestLogger(false, mlog.LvlDebug)}
testAPI := API{logger: mlog.CreateConsoleTestLogger(t)}
t.Run("Returns metadata on success", func(t *testing.T) {
request, _ := http.NewRequest(http.MethodGet, "/ping", nil)

View File

@ -8,7 +8,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/audit"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func (a *API) registerTemplatesRoutes(r *mux.Router) {

View File

@ -15,9 +15,9 @@ import (
"github.com/mattermost/focalboard/server/utils"
"github.com/mattermost/focalboard/server/ws"
mm_model "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/filestore"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
mm_model "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/mattermost/mattermost/server/v8/platform/shared/filestore"
)
const (

View File

@ -5,7 +5,7 @@ import (
"github.com/mattermost/focalboard/server/services/auth"
"github.com/mattermost/focalboard/server/utils"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/pkg/errors"
)

View File

@ -7,7 +7,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/notify"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
var ErrBlocksFromMultipleBoards = errors.New("the block set contain blocks from multiple boards")
@ -54,15 +54,6 @@ func (a *App) DuplicateBlock(boardID string, blockID string, userID string, asTe
return nil
})
go func() {
if uErr := a.UpdateCardLimitTimestamp(); uErr != nil {
a.logger.Error(
"UpdateCardLimitTimestamp failed duplicating a block",
mlog.Err(uErr),
)
}
}()
return blocks, err
}
@ -76,16 +67,6 @@ func (a *App) PatchBlockAndNotify(blockID string, blockPatch *model.BlockPatch,
return nil, err
}
if a.IsCloudLimited() {
containsLimitedBlocks, lErr := a.ContainsLimitedBlocks([]*model.Block{oldBlock})
if lErr != nil {
return nil, lErr
}
if containsLimitedBlocks {
return nil, model.ErrPatchUpdatesLimitedCards
}
}
board, err := a.store.GetBoard(oldBlock.BoardID)
if err != nil {
return nil, err
@ -127,16 +108,6 @@ func (a *App) PatchBlocksAndNotify(teamID string, blockPatches *model.BlockPatch
return err
}
if a.IsCloudLimited() {
containsLimitedBlocks, err := a.ContainsLimitedBlocks(oldBlocks)
if err != nil {
return err
}
if containsLimitedBlocks {
return model.ErrPatchUpdatesLimitedCards
}
}
if err := a.store.PatchBlocks(blockPatches, modifiedByID); err != nil {
return err
}
@ -182,47 +153,9 @@ func (a *App) InsertBlockAndNotify(block *model.Block, modifiedByID string, disa
})
}
go func() {
if uErr := a.UpdateCardLimitTimestamp(); uErr != nil {
a.logger.Error(
"UpdateCardLimitTimestamp failed after inserting a block",
mlog.Err(uErr),
)
}
}()
return err
}
func (a *App) isWithinViewsLimit(boardID string, block *model.Block) (bool, error) {
// ToDo: Cloud Limits have been disabled by design. We should
// revisit the decision and update the related code accordingly
/*
limits, err := a.GetBoardsCloudLimits()
if err != nil {
return false, err
}
if limits.Views == model.LimitUnlimited {
return true, nil
}
views, err := a.store.GetBlocksWithParentAndType(boardID, block.ParentID, model.TypeView)
if err != nil {
return false, err
}
// < rather than <= because we'll be creating new view if this
// check passes. When that view is created, the limit will be reached.
// That's why we need to check for if existing + the being-created
// view doesn't exceed the limit.
return len(views) < limits.Views, nil
*/
return true, nil
}
func (a *App) InsertBlocks(blocks []*model.Block, modifiedByID string) ([]*model.Block, error) {
return a.InsertBlocksAndNotify(blocks, modifiedByID, false)
}
@ -247,20 +180,6 @@ func (a *App) InsertBlocksAndNotify(blocks []*model.Block, modifiedByID string,
needsNotify := make([]*model.Block, 0, len(blocks))
for i := range blocks {
// this check is needed to whitelist inbuilt template
// initialization. They do contain more than 5 views per board.
if boardID != "0" && blocks[i].Type == model.TypeView {
withinLimit, err := a.isWithinViewsLimit(board.ID, blocks[i])
if err != nil {
return nil, err
}
if !withinLimit {
a.logger.Info("views limit reached on board", mlog.String("board_id", blocks[i].ParentID), mlog.String("team_id", board.TeamID))
return nil, model.ErrViewsLimitReached
}
}
err := a.store.InsertBlock(blocks[i], modifiedByID)
if err != nil {
return nil, err
@ -282,15 +201,6 @@ func (a *App) InsertBlocksAndNotify(blocks []*model.Block, modifiedByID string,
return nil
})
go func() {
if err := a.UpdateCardLimitTimestamp(); err != nil {
a.logger.Error(
"UpdateCardLimitTimestamp failed after inserting blocks",
mlog.Err(err),
)
}
}()
return blocks, nil
}
@ -332,15 +242,6 @@ func (a *App) DeleteBlockAndNotify(blockID string, modifiedBy string, disableNot
return nil
})
go func() {
if err := a.UpdateCardLimitTimestamp(); err != nil {
a.logger.Error(
"UpdateCardLimitTimestamp failed after deleting a block",
mlog.Err(err),
)
}
}()
return nil
}
@ -394,15 +295,6 @@ func (a *App) UndeleteBlock(blockID string, modifiedBy string) (*model.Block, er
return nil
})
go func() {
if err := a.UpdateCardLimitTimestamp(); err != nil {
a.logger.Error(
"UpdateCardLimitTimestamp failed after undeleting a block",
mlog.Err(err),
)
}
}()
return block, nil
}

View File

@ -4,12 +4,10 @@ import (
"database/sql"
"testing"
"github.com/stretchr/testify/assert"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
mmModel "github.com/mattermost/mattermost-server/v6/model"
mmModel "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/focalboard/server/model"
)
@ -186,100 +184,6 @@ func TestUndeleteBlock(t *testing.T) {
})
}
func TestIsWithinViewsLimit(t *testing.T) {
t.Skipf("The Cloud Limits feature has been disabled")
th, tearDown := SetupTestHelper(t)
defer tearDown()
fakeLicense := &mmModel.License{
Features: &mmModel.Features{Cloud: mmModel.NewBool(true)},
}
t.Run("within views limit", func(t *testing.T) {
th.Store.EXPECT().GetLicense().Return(fakeLicense)
cloudLimit := &mmModel.ProductLimits{
Boards: &mmModel.BoardsLimits{
Views: mmModel.NewInt(2),
},
}
th.Store.EXPECT().GetCloudLimits().Return(cloudLimit, nil)
th.Store.EXPECT().GetUsedCardsCount().Return(1, nil)
th.Store.EXPECT().GetCardLimitTimestamp().Return(int64(1), nil)
th.Store.EXPECT().GetBlocksWithParentAndType("board_id", "parent_id", "view").Return([]*model.Block{{}}, nil)
withinLimits, err := th.App.isWithinViewsLimit("board_id", &model.Block{ParentID: "parent_id"})
assert.NoError(t, err)
assert.True(t, withinLimits)
})
t.Run("view limit exactly reached", func(t *testing.T) {
th.Store.EXPECT().GetLicense().Return(fakeLicense)
cloudLimit := &mmModel.ProductLimits{
Boards: &mmModel.BoardsLimits{
Views: mmModel.NewInt(1),
},
}
th.Store.EXPECT().GetCloudLimits().Return(cloudLimit, nil)
th.Store.EXPECT().GetUsedCardsCount().Return(1, nil)
th.Store.EXPECT().GetCardLimitTimestamp().Return(int64(1), nil)
th.Store.EXPECT().GetBlocksWithParentAndType("board_id", "parent_id", "view").Return([]*model.Block{{}}, nil)
withinLimits, err := th.App.isWithinViewsLimit("board_id", &model.Block{ParentID: "parent_id"})
assert.NoError(t, err)
assert.False(t, withinLimits)
})
t.Run("view limit already exceeded", func(t *testing.T) {
th.Store.EXPECT().GetLicense().Return(fakeLicense)
cloudLimit := &mmModel.ProductLimits{
Boards: &mmModel.BoardsLimits{
Views: mmModel.NewInt(2),
},
}
th.Store.EXPECT().GetCloudLimits().Return(cloudLimit, nil)
th.Store.EXPECT().GetUsedCardsCount().Return(1, nil)
th.Store.EXPECT().GetCardLimitTimestamp().Return(int64(1), nil)
th.Store.EXPECT().GetBlocksWithParentAndType("board_id", "parent_id", "view").Return([]*model.Block{{}, {}, {}}, nil)
withinLimits, err := th.App.isWithinViewsLimit("board_id", &model.Block{ParentID: "parent_id"})
assert.NoError(t, err)
assert.False(t, withinLimits)
})
t.Run("creating first view", func(t *testing.T) {
th.Store.EXPECT().GetLicense().Return(fakeLicense)
cloudLimit := &mmModel.ProductLimits{
Boards: &mmModel.BoardsLimits{
Views: mmModel.NewInt(2),
},
}
th.Store.EXPECT().GetCloudLimits().Return(cloudLimit, nil)
th.Store.EXPECT().GetUsedCardsCount().Return(1, nil)
th.Store.EXPECT().GetCardLimitTimestamp().Return(int64(1), nil)
th.Store.EXPECT().GetBlocksWithParentAndType("board_id", "parent_id", "view").Return([]*model.Block{}, nil)
withinLimits, err := th.App.isWithinViewsLimit("board_id", &model.Block{ParentID: "parent_id"})
assert.NoError(t, err)
assert.True(t, withinLimits)
})
t.Run("is not a cloud SKU so limits don't apply", func(t *testing.T) {
nonCloudLicense := &mmModel.License{
Features: &mmModel.Features{Cloud: mmModel.NewBool(false)},
}
th.Store.EXPECT().GetLicense().Return(nonCloudLicense)
withinLimits, err := th.App.isWithinViewsLimit("board_id", &model.Block{ParentID: "parent_id"})
assert.NoError(t, err)
assert.True(t, withinLimits)
})
}
func TestInsertBlocks(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
@ -325,12 +229,6 @@ func TestInsertBlocks(t *testing.T) {
}
th.Store.EXPECT().GetLicense().Return(fakeLicense)
cloudLimit := &mmModel.ProductLimits{
Boards: &mmModel.BoardsLimits{
Views: mmModel.NewInt(2),
},
}
th.Store.EXPECT().GetCloudLimits().Return(cloudLimit, nil)
th.Store.EXPECT().GetUsedCardsCount().Return(1, nil)
th.Store.EXPECT().GetCardLimitTimestamp().Return(int64(1), nil)
th.Store.EXPECT().GetBlocksWithParentAndType("test-board-id", "parent_id", "view").Return([]*model.Block{{}}, nil)
@ -357,12 +255,6 @@ func TestInsertBlocks(t *testing.T) {
}
th.Store.EXPECT().GetLicense().Return(fakeLicense)
cloudLimit := &mmModel.ProductLimits{
Boards: &mmModel.BoardsLimits{
Views: mmModel.NewInt(2),
},
}
th.Store.EXPECT().GetCloudLimits().Return(cloudLimit, nil)
th.Store.EXPECT().GetUsedCardsCount().Return(1, nil)
th.Store.EXPECT().GetCardLimitTimestamp().Return(int64(1), nil)
th.Store.EXPECT().GetBlocksWithParentAndType("test-board-id", "parent_id", "view").Return([]*model.Block{{}, {}}, nil)
@ -398,12 +290,6 @@ func TestInsertBlocks(t *testing.T) {
}
th.Store.EXPECT().GetLicense().Return(fakeLicense).Times(2)
cloudLimit := &mmModel.ProductLimits{
Boards: &mmModel.BoardsLimits{
Views: mmModel.NewInt(2),
},
}
th.Store.EXPECT().GetCloudLimits().Return(cloudLimit, nil).Times(2)
th.Store.EXPECT().GetUsedCardsCount().Return(1, nil).Times(2)
th.Store.EXPECT().GetCardLimitTimestamp().Return(int64(1), nil).Times(2)
th.Store.EXPECT().GetBlocksWithParentAndType("test-board-id", "parent_id", "view").Return([]*model.Block{{}}, nil).Times(2)

View File

@ -11,7 +11,7 @@ import (
"github.com/mattermost/focalboard/server/services/notify"
"github.com/mattermost/focalboard/server/utils"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
var (
@ -219,17 +219,6 @@ func (a *App) DuplicateBoard(boardID, userID, toTeam string, asTemplate bool) (*
return nil
})
if len(bab.Blocks) != 0 {
go func() {
if uErr := a.UpdateCardLimitTimestamp(); uErr != nil {
a.logger.Error(
"UpdateCardLimitTimestamp failed after duplicating a board",
mlog.Err(uErr),
)
}
}()
}
return bab, members, err
}
@ -469,15 +458,6 @@ func (a *App) DeleteBoard(boardID, userID string) error {
return nil
})
go func() {
if err := a.UpdateCardLimitTimestamp(); err != nil {
a.logger.Error(
"UpdateCardLimitTimestamp failed after deleting a board",
mlog.Err(err),
)
}
}()
return nil
}
@ -715,14 +695,5 @@ func (a *App) UndeleteBoard(boardID string, modifiedBy string) error {
return nil
})
go func() {
if err := a.UpdateCardLimitTimestamp(); err != nil {
a.logger.Error(
"UpdateCardLimitTimestamp failed after undeleting a board",
mlog.Err(err),
)
}
}()
return nil
}

View File

@ -4,7 +4,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/notify"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func (a *App) CreateBoardsAndBlocks(bab *model.BoardsAndBlocks, userID string, addMember bool) (*model.BoardsAndBlocks, error) {
@ -44,17 +44,6 @@ func (a *App) CreateBoardsAndBlocks(bab *model.BoardsAndBlocks, userID string, a
}
}
if len(newBab.Blocks) != 0 {
go func() {
if uErr := a.UpdateCardLimitTimestamp(); uErr != nil {
a.logger.Error(
"UpdateCardLimitTimestamp failed after creating boards and blocks",
mlog.Err(uErr),
)
}
}()
}
for _, board := range newBab.Boards {
if !board.IsTemplate {
if err := a.addBoardsToDefaultCategory(userID, board.TeamID, []*model.Board{board}); err != nil {
@ -72,16 +61,6 @@ func (a *App) PatchBoardsAndBlocks(pbab *model.PatchBoardsAndBlocks, userID stri
return nil, err
}
if a.IsCloudLimited() {
containsLimitedBlocks, cErr := a.ContainsLimitedBlocks(oldBlocks)
if cErr != nil {
return nil, cErr
}
if containsLimitedBlocks {
return nil, model.ErrPatchUpdatesLimitedCards
}
}
oldBlocksMap := map[string]*model.Block{}
for _, block := range oldBlocks {
oldBlocksMap[block.ID] = block
@ -152,16 +131,5 @@ func (a *App) DeleteBoardsAndBlocks(dbab *model.DeleteBoardsAndBlocks, userID st
return nil
})
if len(dbab.Blocks) != 0 {
go func() {
if uErr := a.UpdateCardLimitTimestamp(); uErr != nil {
a.logger.Error(
"UpdateCardLimitTimestamp failed after deleting boards and blocks",
mlog.Err(uErr),
)
}
}()
}
return nil
}

View File

@ -16,9 +16,6 @@ func TestGetClientConfig(t *testing.T) {
newConfiguration.Telemetry = true
newConfiguration.TelemetryID = "abcde"
newConfiguration.EnablePublicSharedBoards = true
newConfiguration.FeatureFlags = make(map[string]string)
newConfiguration.FeatureFlags["BoardsFeature1"] = "true"
newConfiguration.FeatureFlags["BoardsFeature2"] = "true"
newConfiguration.TeammateNameDisplay = "username"
th.App.SetConfig(&newConfiguration)
@ -26,7 +23,6 @@ func TestGetClientConfig(t *testing.T) {
require.True(t, clientConfig.EnablePublicSharedBoards)
require.True(t, clientConfig.Telemetry)
require.Equal(t, "abcde", clientConfig.TelemetryID)
require.Equal(t, 2, len(clientConfig.FeatureFlags))
require.Equal(t, "username", clientConfig.TeammateNameDisplay)
})
}

View File

@ -1,334 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package app
import (
"errors"
"fmt"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
mmModel "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/utils"
)
var ErrNilPluginAPI = errors.New("server not running in plugin mode")
// GetBoardsCloudLimits returns the limits of the server, and an empty
// limits struct if there are no limits set.
func (a *App) GetBoardsCloudLimits() (*model.BoardsCloudLimits, error) {
// ToDo: Cloud Limits have been disabled by design. We should
// revisit the decision and update the related code accordingly
/*
if !a.IsCloud() {
return &model.BoardsCloudLimits{}, nil
}
productLimits, err := a.store.GetCloudLimits()
if err != nil {
return nil, err
}
usedCards, err := a.store.GetUsedCardsCount()
if err != nil {
return nil, err
}
cardLimitTimestamp, err := a.store.GetCardLimitTimestamp()
if err != nil {
return nil, err
}
boardsCloudLimits := &model.BoardsCloudLimits{
UsedCards: usedCards,
CardLimitTimestamp: cardLimitTimestamp,
}
if productLimits != nil && productLimits.Boards != nil {
if productLimits.Boards.Cards != nil {
boardsCloudLimits.Cards = *productLimits.Boards.Cards
}
if productLimits.Boards.Views != nil {
boardsCloudLimits.Views = *productLimits.Boards.Views
}
}
return boardsCloudLimits, nil
*/
return &model.BoardsCloudLimits{}, nil
}
func (a *App) GetUsedCardsCount() (int, error) {
return a.store.GetUsedCardsCount()
}
// IsCloud returns true if the server is running as a plugin in a
// cloud licensed server.
func (a *App) IsCloud() bool {
return utils.IsCloudLicense(a.store.GetLicense())
}
// IsCloudLimited returns true if the server is running in cloud mode
// and the card limit has been set.
func (a *App) IsCloudLimited() bool {
// ToDo: Cloud Limits have been disabled by design. We should
// revisit the decision and update the related code accordingly
// return a.CardLimit() != 0 && a.IsCloud()
return false
}
// SetCloudLimits sets the limits of the server.
func (a *App) SetCloudLimits(limits *mmModel.ProductLimits) error {
oldCardLimit := a.CardLimit()
// if the limit object doesn't come complete, we assume limits are
// being disabled
cardLimit := 0
if limits != nil && limits.Boards != nil && limits.Boards.Cards != nil {
cardLimit = *limits.Boards.Cards
}
if oldCardLimit != cardLimit {
a.logger.Info(
"setting new cloud limits",
mlog.Int("oldCardLimit", oldCardLimit),
mlog.Int("cardLimit", cardLimit),
)
a.SetCardLimit(cardLimit)
return a.doUpdateCardLimitTimestamp()
}
a.logger.Info(
"setting new cloud limits, equivalent to the existing ones",
mlog.Int("cardLimit", cardLimit),
)
return nil
}
// doUpdateCardLimitTimestamp performs the update without running any
// checks.
func (a *App) doUpdateCardLimitTimestamp() error {
cardLimitTimestamp, err := a.store.UpdateCardLimitTimestamp(a.CardLimit())
if err != nil {
return err
}
a.wsAdapter.BroadcastCardLimitTimestampChange(cardLimitTimestamp)
return nil
}
// UpdateCardLimitTimestamp checks if the server is a cloud instance
// with limits applied, and if that's true, recalculates the card
// limit timestamp and propagates the new one to the connected
// clients.
func (a *App) UpdateCardLimitTimestamp() error {
if !a.IsCloudLimited() {
return nil
}
return a.doUpdateCardLimitTimestamp()
}
// getTemplateMapForBlocks gets all board ids for the blocks, and
// builds a map with the board IDs as the key and their isTemplate
// field as the value.
func (a *App) getTemplateMapForBlocks(blocks []*model.Block) (map[string]bool, error) {
boardMap := map[string]*model.Board{}
for _, block := range blocks {
if _, ok := boardMap[block.BoardID]; !ok {
board, err := a.store.GetBoard(block.BoardID)
if err != nil {
return nil, err
}
boardMap[block.BoardID] = board
}
}
templateMap := map[string]bool{}
for boardID, board := range boardMap {
templateMap[boardID] = board.IsTemplate
}
return templateMap, nil
}
// ApplyCloudLimits takes a set of blocks and, if the server is cloud
// limited, limits those that are outside of the card limit and don't
// belong to a template.
func (a *App) ApplyCloudLimits(blocks []*model.Block) ([]*model.Block, error) {
// if there is no limit currently being applied, return
if !a.IsCloudLimited() {
return blocks, nil
}
cardLimitTimestamp, err := a.store.GetCardLimitTimestamp()
if err != nil {
return nil, err
}
templateMap, err := a.getTemplateMapForBlocks(blocks)
if err != nil {
return nil, err
}
limitedBlocks := make([]*model.Block, len(blocks))
for i, block := range blocks {
// if the block belongs to a template, it will never be
// limited
if isTemplate, ok := templateMap[block.BoardID]; ok && isTemplate {
limitedBlocks[i] = block
continue
}
if block.ShouldBeLimited(cardLimitTimestamp) {
limitedBlocks[i] = block.GetLimited()
} else {
limitedBlocks[i] = block
}
}
return limitedBlocks, nil
}
// ContainsLimitedBlocks checks if a list of blocks contain any block
// that references a limited card.
func (a *App) ContainsLimitedBlocks(blocks []*model.Block) (bool, error) {
cardLimitTimestamp, err := a.store.GetCardLimitTimestamp()
if err != nil {
return false, err
}
if cardLimitTimestamp == 0 {
return false, nil
}
cards := []*model.Block{}
cardIDMap := map[string]bool{}
for _, block := range blocks {
switch block.Type {
case model.TypeCard:
cards = append(cards, block)
default:
cardIDMap[block.ParentID] = true
}
}
cardIDs := []string{}
// if the card is already present on the set, we don't need to
// fetch it from the database
for cardID := range cardIDMap {
alreadyPresent := false
for _, card := range cards {
if card.ID == cardID {
alreadyPresent = true
break
}
}
if !alreadyPresent {
cardIDs = append(cardIDs, cardID)
}
}
if len(cardIDs) > 0 {
fetchedCards, fErr := a.store.GetBlocksByIDs(cardIDs)
if fErr != nil {
return false, fErr
}
cards = append(cards, fetchedCards...)
}
templateMap, err := a.getTemplateMapForBlocks(cards)
if err != nil {
return false, err
}
for _, card := range cards {
isTemplate, ok := templateMap[card.BoardID]
if !ok {
return false, newErrBoardNotFoundInTemplateMap(card.BoardID)
}
// if the block belongs to a template, it will never be
// limited
if isTemplate {
continue
}
if card.ShouldBeLimited(cardLimitTimestamp) {
return true, nil
}
}
return false, nil
}
type errBoardNotFoundInTemplateMap struct {
id string
}
func newErrBoardNotFoundInTemplateMap(id string) *errBoardNotFoundInTemplateMap {
return &errBoardNotFoundInTemplateMap{id}
}
func (eb *errBoardNotFoundInTemplateMap) Error() string {
return fmt.Sprintf("board %q not found in template map", eb.id)
}
func (a *App) NotifyPortalAdminsUpgradeRequest(teamID string) error {
if a.servicesAPI == nil {
return ErrNilPluginAPI
}
team, err := a.store.GetTeam(teamID)
if err != nil {
return err
}
var ofWhat string
if team == nil {
ofWhat = "your organization"
} else {
ofWhat = team.Title
}
message := fmt.Sprintf("A member of %s has notified you to upgrade this workspace before the trial ends.", ofWhat)
page := 0
getUsersOptions := &mmModel.UserGetOptions{
Active: true,
Role: mmModel.SystemAdminRoleId,
PerPage: 50,
Page: page,
}
for ; true; page++ {
getUsersOptions.Page = page
systemAdmins, appErr := a.servicesAPI.GetUsersFromProfiles(getUsersOptions)
if appErr != nil {
a.logger.Error("failed to fetch system admins", mlog.Int("page_size", getUsersOptions.PerPage), mlog.Int("page", page), mlog.Err(appErr))
return appErr
}
if len(systemAdmins) == 0 {
break
}
receiptUserIDs := []string{}
for _, systemAdmin := range systemAdmins {
receiptUserIDs = append(receiptUserIDs, systemAdmin.Id)
}
if err := a.store.SendMessage(message, "custom_cloud_upgrade_nudge", receiptUserIDs); err != nil {
return err
}
}
return nil
}

View File

@ -1,780 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package app
import (
"database/sql"
"testing"
"github.com/stretchr/testify/assert"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
mmModel "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/focalboard/server/model"
mockservicesapi "github.com/mattermost/focalboard/server/model/mocks"
)
func TestIsCloud(t *testing.T) {
t.Run("if it's not running on plugin mode", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
th.Store.EXPECT().GetLicense().Return(nil)
require.False(t, th.App.IsCloud())
})
t.Run("if it's running on plugin mode but the license is incomplete", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
fakeLicense := &mmModel.License{}
th.Store.EXPECT().GetLicense().Return(fakeLicense)
require.False(t, th.App.IsCloud())
fakeLicense = &mmModel.License{Features: &mmModel.Features{}}
th.Store.EXPECT().GetLicense().Return(fakeLicense)
require.False(t, th.App.IsCloud())
})
t.Run("if it's running on plugin mode, with a non-cloud license", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
fakeLicense := &mmModel.License{
Features: &mmModel.Features{Cloud: mmModel.NewBool(false)},
}
th.Store.EXPECT().GetLicense().Return(fakeLicense)
require.False(t, th.App.IsCloud())
})
t.Run("if it's running on plugin mode with a cloud license", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
fakeLicense := &mmModel.License{
Features: &mmModel.Features{Cloud: mmModel.NewBool(true)},
}
th.Store.EXPECT().GetLicense().Return(fakeLicense)
require.True(t, th.App.IsCloud())
})
}
func TestIsCloudLimited(t *testing.T) {
t.Skipf("The Cloud Limits feature has been disabled")
t.Run("if no limit has been set, it should be false", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
require.Zero(t, th.App.CardLimit())
require.False(t, th.App.IsCloudLimited())
})
t.Run("if the limit is set, it should be true", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
fakeLicense := &mmModel.License{
Features: &mmModel.Features{Cloud: mmModel.NewBool(true)},
}
th.Store.EXPECT().GetLicense().Return(fakeLicense)
th.App.SetCardLimit(5)
require.True(t, th.App.IsCloudLimited())
})
}
func TestSetCloudLimits(t *testing.T) {
t.Skipf("The Cloud Limits feature has been disabled")
t.Run("if the limits are empty, it should do nothing", func(t *testing.T) {
t.Run("limits empty", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
require.Zero(t, th.App.CardLimit())
require.NoError(t, th.App.SetCloudLimits(nil))
require.Zero(t, th.App.CardLimit())
})
t.Run("limits not empty but board limits empty", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
require.Zero(t, th.App.CardLimit())
limits := &mmModel.ProductLimits{}
require.NoError(t, th.App.SetCloudLimits(limits))
require.Zero(t, th.App.CardLimit())
})
t.Run("limits not empty but board limits values empty", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
require.Zero(t, th.App.CardLimit())
limits := &mmModel.ProductLimits{
Boards: &mmModel.BoardsLimits{},
}
require.NoError(t, th.App.SetCloudLimits(limits))
require.Zero(t, th.App.CardLimit())
})
})
t.Run("if the limits are not empty, it should update them and calculate the new timestamp", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
require.Zero(t, th.App.CardLimit())
newCardLimitTimestamp := int64(27)
th.Store.EXPECT().UpdateCardLimitTimestamp(5).Return(newCardLimitTimestamp, nil)
limits := &mmModel.ProductLimits{
Boards: &mmModel.BoardsLimits{Cards: mmModel.NewInt(5)},
}
require.NoError(t, th.App.SetCloudLimits(limits))
require.Equal(t, 5, th.App.CardLimit())
})
t.Run("if the limits are already set and we unset them, the timestamp will be unset too", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
th.App.SetCardLimit(20)
th.Store.EXPECT().UpdateCardLimitTimestamp(0)
require.NoError(t, th.App.SetCloudLimits(nil))
require.Zero(t, th.App.CardLimit())
})
t.Run("if the limits are already set and we try to set the same ones again", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
th.App.SetCardLimit(20)
// the call to update card limit timestamp should not happen
// as the limits didn't change
th.Store.EXPECT().UpdateCardLimitTimestamp(gomock.Any()).Times(0)
limits := &mmModel.ProductLimits{
Boards: &mmModel.BoardsLimits{Cards: mmModel.NewInt(20)},
}
require.NoError(t, th.App.SetCloudLimits(limits))
require.Equal(t, 20, th.App.CardLimit())
})
}
func TestUpdateCardLimitTimestamp(t *testing.T) {
t.Skipf("The Cloud Limits feature has been disabled")
fakeLicense := &mmModel.License{
Features: &mmModel.Features{Cloud: mmModel.NewBool(true)},
}
t.Run("if the server is a cloud instance but not limited, it should do nothing", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
require.Zero(t, th.App.CardLimit())
// the license check will not be done as the limit not being
// set is enough for the method to return
th.Store.EXPECT().GetLicense().Times(0)
// no call to UpdateCardLimitTimestamp should happen as the
// method should shortcircuit if not cloud limited
th.Store.EXPECT().UpdateCardLimitTimestamp(gomock.Any()).Times(0)
require.NoError(t, th.App.UpdateCardLimitTimestamp())
})
t.Run("if the server is a cloud instance and the timestamp is set, it should run the update", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
th.App.SetCardLimit(5)
th.Store.EXPECT().GetLicense().Return(fakeLicense)
// no call to UpdateCardLimitTimestamp should happen as the
// method should shortcircuit if not cloud limited
th.Store.EXPECT().UpdateCardLimitTimestamp(5)
require.NoError(t, th.App.UpdateCardLimitTimestamp())
})
}
func TestGetTemplateMapForBlocks(t *testing.T) {
t.Skipf("The Cloud Limits feature has been disabled")
t.Run("should fetch the necessary boards from the database", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
board1 := &model.Board{
ID: "board1",
Type: model.BoardTypeOpen,
IsTemplate: true,
}
board2 := &model.Board{
ID: "board2",
Type: model.BoardTypeOpen,
IsTemplate: false,
}
blocks := []*model.Block{
{
ID: "card1",
Type: model.TypeCard,
ParentID: "board1",
BoardID: "board1",
},
{
ID: "card2",
Type: model.TypeCard,
ParentID: "board2",
BoardID: "board2",
},
{
ID: "text2",
Type: model.TypeText,
ParentID: "card2",
BoardID: "board2",
},
}
th.Store.EXPECT().
GetBoard("board1").
Return(board1, nil).
Times(1)
th.Store.EXPECT().
GetBoard("board2").
Return(board2, nil).
Times(1)
templateMap, err := th.App.getTemplateMapForBlocks(blocks)
require.NoError(t, err)
require.Len(t, templateMap, 2)
require.Contains(t, templateMap, "board1")
require.True(t, templateMap["board1"])
require.Contains(t, templateMap, "board2")
require.False(t, templateMap["board2"])
})
t.Run("should fail if the board is not in the database", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
blocks := []*model.Block{
{
ID: "card1",
Type: model.TypeCard,
ParentID: "board1",
BoardID: "board1",
},
{
ID: "card2",
Type: model.TypeCard,
ParentID: "board2",
BoardID: "board2",
},
}
th.Store.EXPECT().
GetBoard("board1").
Return(nil, sql.ErrNoRows).
Times(1)
templateMap, err := th.App.getTemplateMapForBlocks(blocks)
require.ErrorIs(t, err, sql.ErrNoRows)
require.Empty(t, templateMap)
})
}
func TestApplyCloudLimits(t *testing.T) {
t.Skipf("The Cloud Limits feature has been disabled")
fakeLicense := &mmModel.License{
Features: &mmModel.Features{Cloud: mmModel.NewBool(true)},
}
board1 := &model.Board{
ID: "board1",
Type: model.BoardTypeOpen,
IsTemplate: false,
}
template := &model.Board{
ID: "template",
Type: model.BoardTypeOpen,
IsTemplate: true,
}
blocks := []*model.Block{
{
ID: "card1",
Type: model.TypeCard,
ParentID: "board1",
BoardID: "board1",
UpdateAt: 100,
},
{
ID: "text1",
Type: model.TypeText,
ParentID: "card1",
BoardID: "board1",
UpdateAt: 100,
},
{
ID: "card2",
Type: model.TypeCard,
ParentID: "board1",
BoardID: "board1",
UpdateAt: 200,
},
{
ID: "card-from-template",
Type: model.TypeCard,
ParentID: "template",
BoardID: "template",
UpdateAt: 1,
},
}
t.Run("if the server is not limited, it should return the blocks untouched", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
require.Zero(t, th.App.CardLimit())
newBlocks, err := th.App.ApplyCloudLimits(blocks)
require.NoError(t, err)
require.ElementsMatch(t, blocks, newBlocks)
})
t.Run("if the server is limited, it should limit the blocks that are beyond the card limit timestamp", func(t *testing.T) {
findBlock := func(blocks []*model.Block, id string) *model.Block {
for _, block := range blocks {
if block.ID == id {
return block
}
}
require.FailNow(t, "block %s not found", id)
return &model.Block{} // this should never be reached
}
th, tearDown := SetupTestHelper(t)
defer tearDown()
th.App.SetCardLimit(5)
th.Store.EXPECT().GetLicense().Return(fakeLicense)
th.Store.EXPECT().GetCardLimitTimestamp().Return(int64(150), nil)
th.Store.EXPECT().GetBoard("board1").Return(board1, nil).Times(1)
th.Store.EXPECT().GetBoard("template").Return(template, nil).Times(1)
newBlocks, err := th.App.ApplyCloudLimits(blocks)
require.NoError(t, err)
// should be limited as it's beyond the threshold
require.True(t, findBlock(newBlocks, "card1").Limited)
// only cards are limited
require.False(t, findBlock(newBlocks, "text1").Limited)
// should not be limited as it's not beyond the threshold
require.False(t, findBlock(newBlocks, "card2").Limited)
// cards belonging to templates are never limited
require.False(t, findBlock(newBlocks, "card-from-template").Limited)
})
}
func TestContainsLimitedBlocks(t *testing.T) {
t.Skipf("The Cloud Limits feature has been disabled")
// for all the following tests, the timestamp will be set to 150,
// which means that blocks with an UpdateAt set to 100 will be
// outside the active window and possibly limited, and blocks with
// UpdateAt set to 200 will not
t.Run("should return false if the card limit timestamp is zero", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
blocks := []*model.Block{
{
ID: "card1",
Type: model.TypeCard,
ParentID: "board1",
BoardID: "board1",
UpdateAt: 100,
},
}
th.Store.EXPECT().GetCardLimitTimestamp().Return(int64(0), nil)
containsLimitedBlocks, err := th.App.ContainsLimitedBlocks(blocks)
require.NoError(t, err)
require.False(t, containsLimitedBlocks)
})
t.Run("should return true if the block set contains a card that is limited", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
blocks := []*model.Block{
{
ID: "card1",
Type: model.TypeCard,
ParentID: "board1",
BoardID: "board1",
UpdateAt: 100,
},
}
board1 := &model.Board{
ID: "board1",
Type: model.BoardTypePrivate,
}
th.App.SetCardLimit(500)
cardLimitTimestamp := int64(150)
th.Store.EXPECT().GetCardLimitTimestamp().Return(cardLimitTimestamp, nil)
th.Store.EXPECT().GetBoard("board1").Return(board1, nil)
containsLimitedBlocks, err := th.App.ContainsLimitedBlocks(blocks)
require.NoError(t, err)
require.True(t, containsLimitedBlocks)
})
t.Run("should return false if that same block belongs to a template", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
blocks := []*model.Block{
{
ID: "card1",
Type: model.TypeCard,
ParentID: "board1",
BoardID: "board1",
UpdateAt: 100,
},
}
board1 := &model.Board{
ID: "board1",
Type: model.BoardTypeOpen,
IsTemplate: true,
}
th.App.SetCardLimit(500)
cardLimitTimestamp := int64(150)
th.Store.EXPECT().GetCardLimitTimestamp().Return(cardLimitTimestamp, nil)
th.Store.EXPECT().GetBoard("board1").Return(board1, nil)
containsLimitedBlocks, err := th.App.ContainsLimitedBlocks(blocks)
require.NoError(t, err)
require.False(t, containsLimitedBlocks)
})
t.Run("should return true if the block contains a content block that belongs to a card that should be limited", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
blocks := []*model.Block{
{
ID: "text1",
Type: model.TypeText,
ParentID: "card1",
BoardID: "board1",
UpdateAt: 200,
},
}
card1 := &model.Block{
ID: "card1",
Type: model.TypeCard,
ParentID: "board1",
BoardID: "board1",
UpdateAt: 100,
}
board1 := &model.Board{
ID: "board1",
Type: model.BoardTypeOpen,
}
th.App.SetCardLimit(500)
cardLimitTimestamp := int64(150)
th.Store.EXPECT().GetCardLimitTimestamp().Return(cardLimitTimestamp, nil)
th.Store.EXPECT().GetBlocksByIDs([]string{"card1"}).Return([]*model.Block{card1}, nil)
th.Store.EXPECT().GetBoard("board1").Return(board1, nil)
containsLimitedBlocks, err := th.App.ContainsLimitedBlocks(blocks)
require.NoError(t, err)
require.True(t, containsLimitedBlocks)
})
t.Run("should return false if that same block belongs to a card that is inside the active window", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
blocks := []*model.Block{
{
ID: "text1",
Type: model.TypeText,
ParentID: "card1",
BoardID: "board1",
UpdateAt: 200,
},
}
card1 := &model.Block{
ID: "card1",
Type: model.TypeCard,
ParentID: "board1",
BoardID: "board1",
UpdateAt: 200,
}
board1 := &model.Board{
ID: "board1",
Type: model.BoardTypeOpen,
}
th.App.SetCardLimit(500)
cardLimitTimestamp := int64(150)
th.Store.EXPECT().GetCardLimitTimestamp().Return(cardLimitTimestamp, nil)
th.Store.EXPECT().GetBlocksByIDs([]string{"card1"}).Return([]*model.Block{card1}, nil)
th.Store.EXPECT().GetBoard("board1").Return(board1, nil)
containsLimitedBlocks, err := th.App.ContainsLimitedBlocks(blocks)
require.NoError(t, err)
require.False(t, containsLimitedBlocks)
})
t.Run("should reach to the database to fetch the necessary information only in an efficient way", func(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
blocks := []*model.Block{
// a content block that references a card that needs
// fetching
{
ID: "text1",
Type: model.TypeText,
ParentID: "card1",
BoardID: "board1",
UpdateAt: 100,
},
// a board that needs fetching referenced by a card and a content block
{
ID: "card2",
Type: model.TypeCard,
ParentID: "board2",
BoardID: "board2",
// per timestamp should be limited but the board is a
// template
UpdateAt: 100,
},
{
ID: "text2",
Type: model.TypeText,
ParentID: "card2",
BoardID: "board2",
UpdateAt: 200,
},
// a content block that references a card and a board,
// both absent
{
ID: "image3",
Type: model.TypeImage,
ParentID: "card3",
BoardID: "board3",
UpdateAt: 100,
},
}
card1 := &model.Block{
ID: "card1",
Type: model.TypeCard,
ParentID: "board1",
BoardID: "board1",
UpdateAt: 200,
}
card3 := &model.Block{
ID: "card3",
Type: model.TypeCard,
ParentID: "board3",
BoardID: "board3",
UpdateAt: 200,
}
board1 := &model.Board{
ID: "board1",
Type: model.BoardTypeOpen,
}
board2 := &model.Board{
ID: "board2",
Type: model.BoardTypeOpen,
IsTemplate: true,
}
board3 := &model.Board{
ID: "board3",
Type: model.BoardTypePrivate,
}
th.App.SetCardLimit(500)
cardLimitTimestamp := int64(150)
th.Store.EXPECT().GetCardLimitTimestamp().Return(cardLimitTimestamp, nil)
th.Store.EXPECT().GetBlocksByIDs(gomock.InAnyOrder([]string{"card1", "card3"})).Return([]*model.Block{card1, card3}, nil)
th.Store.EXPECT().GetBoard("board1").Return(board1, nil)
th.Store.EXPECT().GetBoard("board2").Return(board2, nil)
th.Store.EXPECT().GetBoard("board3").Return(board3, nil)
containsLimitedBlocks, err := th.App.ContainsLimitedBlocks(blocks)
require.NoError(t, err)
require.False(t, containsLimitedBlocks)
})
}
func TestNotifyPortalAdminsUpgradeRequest(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
t.Run("should send message", func(t *testing.T) {
ctrl := gomock.NewController(t)
servicesAPI := mockservicesapi.NewMockServicesAPI(ctrl)
sysAdmin1 := &mmModel.User{
Id: "michael-scott",
Username: "Michael Scott",
}
sysAdmin2 := &mmModel.User{
Id: "dwight-schrute",
Username: "Dwight Schrute",
}
getUsersOptionsPage0 := &mmModel.UserGetOptions{
Active: true,
Role: mmModel.SystemAdminRoleId,
PerPage: 50,
Page: 0,
}
servicesAPI.EXPECT().GetUsersFromProfiles(getUsersOptionsPage0).Return([]*mmModel.User{sysAdmin1, sysAdmin2}, nil)
getUsersOptionsPage1 := &mmModel.UserGetOptions{
Active: true,
Role: mmModel.SystemAdminRoleId,
PerPage: 50,
Page: 1,
}
servicesAPI.EXPECT().GetUsersFromProfiles(getUsersOptionsPage1).Return([]*mmModel.User{}, nil)
th.App.servicesAPI = servicesAPI
team := &model.Team{
Title: "Dunder Mifflin",
}
th.Store.EXPECT().GetTeam("team-id-1").Return(team, nil)
th.Store.EXPECT().SendMessage(gomock.Any(), "custom_cloud_upgrade_nudge", gomock.Any()).Return(nil).Times(1)
err := th.App.NotifyPortalAdminsUpgradeRequest("team-id-1")
assert.NoError(t, err)
})
t.Run("no sys admins found", func(t *testing.T) {
ctrl := gomock.NewController(t)
servicesAPI := mockservicesapi.NewMockServicesAPI(ctrl)
getUsersOptionsPage0 := &mmModel.UserGetOptions{
Active: true,
Role: mmModel.SystemAdminRoleId,
PerPage: 50,
Page: 0,
}
servicesAPI.EXPECT().GetUsersFromProfiles(getUsersOptionsPage0).Return([]*mmModel.User{}, nil)
th.App.servicesAPI = servicesAPI
team := &model.Team{
Title: "Dunder Mifflin",
}
th.Store.EXPECT().GetTeam("team-id-1").Return(team, nil)
err := th.App.NotifyPortalAdminsUpgradeRequest("team-id-1")
assert.NoError(t, err)
})
t.Run("iterate multiple pages", func(t *testing.T) {
ctrl := gomock.NewController(t)
servicesAPI := mockservicesapi.NewMockServicesAPI(ctrl)
sysAdmin1 := &mmModel.User{
Id: "michael-scott",
Username: "Michael Scott",
}
sysAdmin2 := &mmModel.User{
Id: "dwight-schrute",
Username: "Dwight Schrute",
}
getUsersOptionsPage0 := &mmModel.UserGetOptions{
Active: true,
Role: mmModel.SystemAdminRoleId,
PerPage: 50,
Page: 0,
}
servicesAPI.EXPECT().GetUsersFromProfiles(getUsersOptionsPage0).Return([]*mmModel.User{sysAdmin1}, nil)
getUsersOptionsPage1 := &mmModel.UserGetOptions{
Active: true,
Role: mmModel.SystemAdminRoleId,
PerPage: 50,
Page: 1,
}
servicesAPI.EXPECT().GetUsersFromProfiles(getUsersOptionsPage1).Return([]*mmModel.User{sysAdmin2}, nil)
getUsersOptionsPage2 := &mmModel.UserGetOptions{
Active: true,
Role: mmModel.SystemAdminRoleId,
PerPage: 50,
Page: 2,
}
servicesAPI.EXPECT().GetUsersFromProfiles(getUsersOptionsPage2).Return([]*mmModel.User{}, nil)
th.App.servicesAPI = servicesAPI
team := &model.Team{
Title: "Dunder Mifflin",
}
th.Store.EXPECT().GetTeam("team-id-1").Return(team, nil)
th.Store.EXPECT().SendMessage(gomock.Any(), "custom_cloud_upgrade_nudge", gomock.Any()).Return(nil).Times(2)
err := th.App.NotifyPortalAdminsUpgradeRequest("team-id-1")
assert.NoError(t, err)
})
}

View File

@ -160,6 +160,7 @@ func TestMoveContentBlock(t *testing.T) {
for _, tc := range ttCases {
t.Run(tc.name, func(t *testing.T) {
tc := tc
if tc.parentBlock != nil {
if tc.parentBlock.ID == "invalid-card" {
th.Store.EXPECT().GetBlock(tc.srcBlock.ParentID).Return(nil, model.NewErrNotFound("test"))

View File

@ -9,7 +9,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/wiggin77/merror"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
var (

View File

@ -8,11 +8,11 @@ import (
"strings"
"github.com/mattermost/focalboard/server/model"
mm_model "github.com/mattermost/mattermost-server/v6/model"
mm_model "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/focalboard/server/utils"
"github.com/mattermost/mattermost-server/v6/shared/filestore"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/mattermost/mattermost/server/v8/platform/shared/filestore"
)
const emptyString = "empty"

View File

@ -13,10 +13,10 @@ import (
"github.com/stretchr/testify/assert"
"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"
mm_model "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/plugin/plugintest/mock"
"github.com/mattermost/mattermost/server/v8/platform/shared/filestore"
"github.com/mattermost/mattermost/server/v8/platform/shared/filestore/mocks"
)
const (

View File

@ -17,8 +17,8 @@ import (
"github.com/mattermost/focalboard/server/services/webhook"
"github.com/mattermost/focalboard/server/ws"
"github.com/mattermost/mattermost-server/v6/shared/filestore/mocks"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/mattermost/mattermost/server/v8/platform/shared/filestore/mocks"
)
type TestHelper struct {
@ -35,7 +35,7 @@ func SetupTestHelper(t *testing.T) (*TestHelper, func()) {
store := mockstore.NewMockStore(ctrl)
filesBackend := &mocks.FileBackend{}
auth := auth.New(&cfg, store, nil)
logger := mlog.CreateConsoleTestLogger(false, mlog.LvlDebug)
logger, _ := mlog.NewLogger()
sessionToken := "TESTTOKEN"
wsserver := ws.NewServer(auth, sessionToken, false, logger, store)
webhook := webhook.NewClient(&cfg, logger)
@ -43,7 +43,7 @@ func SetupTestHelper(t *testing.T) (*TestHelper, func()) {
mockStore := permissionsMocks.NewMockStore(ctrl)
mockAPI := mmpermissionsMocks.NewMockAPI(ctrl)
permissions := mmpermissions.New(mockStore, mockAPI, mlog.CreateConsoleTestLogger(true, mlog.LvlError))
permissions := mmpermissions.New(mockStore, mockAPI, mlog.CreateConsoleTestLogger(t))
appServices := Services{
Auth: auth,

View File

@ -16,7 +16,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/utils"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
const (

View File

@ -3,7 +3,7 @@ package app
import (
"context"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
// initialize is called when the App is first created.

View File

@ -1,83 +0,0 @@
package app
import (
"github.com/mattermost/focalboard/server/model"
mmModel "github.com/mattermost/mattermost-server/v6/model"
"github.com/pkg/errors"
)
func (a *App) GetTeamBoardsInsights(userID string, teamID string, opts *mmModel.InsightsOpts) (*model.BoardInsightsList, error) {
// check if server is properly licensed, and user is not a guest
userPermitted, err := insightPermissionGate(a, userID, false)
if err != nil {
return nil, err
}
if !userPermitted {
return nil, errors.New("User isn't authorized to access insights.")
}
boardIDs, err := getUserBoards(userID, teamID, a)
if err != nil {
return nil, err
}
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) {
// check if server is properly licensed, and user is not a guest
userPermitted, err := insightPermissionGate(a, userID, true)
if err != nil {
return nil, err
}
if !userPermitted {
return nil, errors.New("User isn't authorized to access insights.")
}
boardIDs, err := getUserBoards(userID, teamID, a)
if err != nil {
return nil, err
}
return a.store.GetUserBoardsInsights(teamID, userID, opts.StartUnixMilli, opts.Page*opts.PerPage, opts.PerPage, boardIDs)
}
func insightPermissionGate(a *App, userID string, isMyInsights bool) (bool, error) {
licenseError := errors.New("invalid license/authorization to use insights API")
guestError := errors.New("guests aren't authorized to use insights API")
lic := a.store.GetLicense()
user, err := a.store.GetUserByID(userID)
if err != nil {
return false, err
}
if user.IsGuest {
return false, guestError
}
if lic == nil && !isMyInsights {
a.logger.Debug("Deployment doesn't have a license")
return false, licenseError
}
if !isMyInsights && (lic.SkuShortName != mmModel.LicenseShortSkuProfessional && lic.SkuShortName != mmModel.LicenseShortSkuEnterprise) {
return false, licenseError
}
return true, nil
}
func (a *App) GetUserTimezone(userID string) (string, error) {
return a.store.GetUserTimezone(userID)
}
func getUserBoards(userID string, teamID string, a *App) ([]string, error) {
// get boards accessible by user and filter boardIDs
boards, err := a.store.GetBoardsForUserAndTeam(userID, teamID, true)
if err != nil {
return nil, errors.New("error getting boards for user")
}
boardIDs := make([]string, 0, len(boards))
for _, board := range boards {
boardIDs = append(boardIDs, board.ID)
}
return boardIDs, nil
}

View File

@ -1,89 +0,0 @@
package app
import (
"testing"
"github.com/mattermost/focalboard/server/model"
mmModel "github.com/mattermost/mattermost-server/v6/model"
"github.com/stretchr/testify/require"
)
var mockInsightsBoards = []*model.Board{
{
ID: "mock-user-workspace-id",
Title: "MockUserWorkspace",
},
}
var mockTeamInsights = []*model.BoardInsight{
{
BoardID: "board-id-1",
},
{
BoardID: "board-id-2",
},
}
var mockTeamInsightsList = &model.BoardInsightsList{
InsightsListData: mmModel.InsightsListData{HasNext: false},
Items: mockTeamInsights,
}
type insightError struct {
msg string
}
func (ie insightError) Error() string {
return ie.msg
}
func TestGetTeamAndUserBoardsInsights(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
t.Run("success query", func(t *testing.T) {
fakeLicense := &mmModel.License{Features: &mmModel.Features{}, SkuShortName: mmModel.LicenseShortSkuEnterprise}
th.Store.EXPECT().GetLicense().Return(fakeLicense).AnyTimes()
fakeUser := &model.User{
ID: "user-id",
IsGuest: false,
}
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", 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)
require.Len(t, results.Items, 2)
th.Store.EXPECT().
GetUserBoardsInsights("team-id", "user-id", int64(0), 0, 10, []string{"mock-user-workspace-id"}).
Return(mockTeamInsightsList, nil)
results, err = th.App.GetUserBoardsInsights("user-id", "team-id", &mmModel.InsightsOpts{StartUnixMilli: 0, Page: 0, PerPage: 10})
require.NoError(t, err)
require.Len(t, results.Items, 2)
})
t.Run("fail query", func(t *testing.T) {
fakeLicense := &mmModel.License{Features: &mmModel.Features{}, SkuShortName: mmModel.LicenseShortSkuEnterprise}
th.Store.EXPECT().GetLicense().Return(fakeLicense).AnyTimes()
fakeUser := &model.User{
ID: "user-id",
IsGuest: false,
}
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", 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)
require.ErrorIs(t, err, insightError{"board-insight-error"})
th.Store.EXPECT().
GetUserBoardsInsights("team-id", "user-id", int64(0), 0, 10, []string{"mock-user-workspace-id"}).
Return(nil, insightError{"board-insight-error"})
_, err = th.App.GetUserBoardsInsights("user-id", "team-id", &mmModel.InsightsOpts{StartUnixMilli: 0, Page: 0, PerPage: 10})
require.Error(t, err)
require.ErrorIs(t, err, insightError{"board-insight-error"})
})
}

View File

@ -1,7 +1,7 @@
package app
import (
mm_model "github.com/mattermost/mattermost-server/v6/model"
mm_model "github.com/mattermost/mattermost/server/public/model"
)
func (a *App) HasPermissionToBoard(userID, boardID string, permission *mm_model.Permission) bool {

8
server/app/statistics.go Normal file
View File

@ -0,0 +1,8 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package app
func (a *App) GetUsedCardsCount() (int, error) {
return a.store.GetUsedCardsCount()
}

View File

@ -4,7 +4,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/utils"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func (a *App) CreateSubscription(sub *model.Subscription) (*model.Subscription, error) {

View File

@ -4,7 +4,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/utils"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func (a *App) GetRootTeam() (*model.Team, error) {

View File

@ -8,7 +8,7 @@ import (
"github.com/mattermost/focalboard/server/assets"
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
const (

View File

@ -8,7 +8,7 @@ import (
"github.com/mattermost/focalboard/server/utils"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/plugin/plugintest/mock"
"github.com/mattermost/mattermost/server/public/plugin/plugintest/mock"
)
func TestApp_initializeTemplates(t *testing.T) {

View File

@ -2,7 +2,7 @@ package app
import (
"github.com/mattermost/focalboard/server/model"
mmModel "github.com/mattermost/mattermost-server/v6/model"
mmModel "github.com/mattermost/mattermost/server/public/model"
)
func (a *App) GetTeamUsers(teamID string, asGuestID string) ([]*model.User, error) {

View File

@ -4,7 +4,7 @@ import (
"testing"
"github.com/mattermost/focalboard/server/model"
mmModel "github.com/mattermost/mattermost-server/v6/model"
mmModel "github.com/mattermost/mattermost/server/public/model"
"github.com/stretchr/testify/assert"
)

View File

@ -13,7 +13,7 @@ import (
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
type TestHelper struct {

View File

@ -12,7 +12,7 @@ import (
"github.com/mattermost/focalboard/server/api"
"github.com/mattermost/focalboard/server/model"
mmModel "github.com/mattermost/mattermost-server/v6/model"
mmModel "github.com/mattermost/mattermost/server/public/model"
)
const (
@ -215,36 +215,6 @@ func (c *Client) GetTeam(teamID string) (*model.Team, *Response) {
return model.TeamFromJSON(r.Body), BuildResponse(r)
}
func (c *Client) GetTeamBoardsInsights(teamID string, userID string, timeRange string, page int, perPage int) (*model.BoardInsightsList, *Response) {
query := fmt.Sprintf("?time_range=%v&page=%v&per_page=%v", timeRange, page, perPage)
r, err := c.DoAPIGet(c.GetTeamRoute(teamID)+"/boards/insights"+query, "")
if err != nil {
return nil, BuildErrorResponse(r, err)
}
defer closeBody(r)
var boardInsightsList *model.BoardInsightsList
if jsonErr := json.NewDecoder(r.Body).Decode(&boardInsightsList); jsonErr != nil {
return nil, BuildErrorResponse(r, jsonErr)
}
return boardInsightsList, BuildResponse(r)
}
func (c *Client) GetUserBoardsInsights(teamID string, userID string, timeRange string, page int, perPage int) (*model.BoardInsightsList, *Response) {
query := fmt.Sprintf("?time_range=%v&page=%v&per_page=%v&team_id=%v", timeRange, page, perPage, teamID)
r, err := c.DoAPIGet(c.GetMeRoute()+"/boards/insights"+query, "")
if err != nil {
return nil, BuildErrorResponse(r, err)
}
defer closeBody(r)
var boardInsightsList *model.BoardInsightsList
if jsonErr := json.NewDecoder(r.Body).Decode(&boardInsightsList); jsonErr != nil {
return nil, BuildErrorResponse(r, jsonErr)
}
return boardInsightsList, BuildResponse(r)
}
func (c *Client) GetBlocksForBoard(boardID string) ([]*model.Block, *Response) {
r, err := c.DoAPIGet(c.GetBlocksRoute(boardID), "")
if err != nil {
@ -973,22 +943,6 @@ func (c *Client) ImportArchive(teamID string, data io.Reader) *Response {
return BuildResponse(r)
}
func (c *Client) GetLimits() (*model.BoardsCloudLimits, *Response) {
r, err := c.DoAPIGet("/limits", "")
if err != nil {
return nil, BuildErrorResponse(r, err)
}
defer closeBody(r)
var limits *model.BoardsCloudLimits
err = json.NewDecoder(r.Body).Decode(&limits)
if err != nil {
return nil, BuildErrorResponse(r, err)
}
return limits, BuildResponse(r)
}
func (c *Client) MoveContentBlock(srcBlockID string, dstBlockID string, where string, userID string) (bool, *Response) {
r, err := c.DoAPIPost("/content-blocks/"+srcBlockID+"/moveto/"+where+"/"+dstBlockID, "")
if err != nil {
@ -999,22 +953,6 @@ func (c *Client) MoveContentBlock(srcBlockID string, dstBlockID string, where st
return true, BuildResponse(r)
}
func (c *Client) GetStatistics() (*model.BoardsStatistics, *Response) {
r, err := c.DoAPIGet("/statistics", "")
if err != nil {
return nil, BuildErrorResponse(r, err)
}
defer closeBody(r)
var stats *model.BoardsStatistics
err = json.NewDecoder(r.Body).Decode(&stats)
if err != nil {
return nil, BuildErrorResponse(r, err)
}
return stats, BuildResponse(r)
}
func (c *Client) GetBoardsForCompliance(teamID string, page, perPage int) (*model.BoardsComplianceResponse, *Response) {
query := fmt.Sprintf("?team_id=%s&page=%d&per_page=%d", teamID, page, perPage)
r, err := c.DoAPIGet("/admin/boards"+query, "")

View File

@ -1,121 +1,118 @@
module github.com/mattermost/focalboard/server
go 1.19
go 1.21
toolchain go1.21.8
require (
github.com/Masterminds/squirrel v1.5.3
github.com/Masterminds/squirrel v1.5.4
github.com/golang/mock v1.6.0
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
github.com/gorilla/mux v1.8.1
github.com/gorilla/websocket v1.5.1
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-20230321114510-b61c096497ac
github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e
github.com/lib/pq v1.10.9
github.com/mattermost/logr/v2 v2.0.21
github.com/mattermost/mattermost/server/public v0.1.3
github.com/mattermost/mattermost/server/v8 v8.0.0-20240529104128-9d30a62c9471
github.com/mattermost/morph v1.1.0
github.com/mattn/go-sqlite3 v2.0.3+incompatible
github.com/mgdelacroix/foundation v0.0.0-20220812143423-0bfc18f73538
github.com/mgdelacroix/foundation v0.0.0-20230510073833-0660207768ef
github.com/oklog/run v1.1.0
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.12.1
github.com/rivo/uniseg v0.4.3
github.com/prometheus/client_golang v1.19.1
github.com/rivo/uniseg v0.4.7
github.com/rudderlabs/analytics-go v3.3.3+incompatible
github.com/sergi/go-diff v1.2.0
github.com/spf13/viper v1.10.1
github.com/stretchr/testify v1.8.1
github.com/wiggin77/merror v1.0.4
golang.org/x/crypto v0.5.0
github.com/sergi/go-diff v1.3.1
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.9.0
github.com/wiggin77/merror v1.0.5
golang.org/x/crypto v0.23.0
)
require (
filippo.io/edwards25519 v1.1.0 // 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.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/fatih/color v1.17.0 // indirect
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.7.0 // indirect
github.com/golang-migrate/migrate/v4 v4.15.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/uuid v1.3.0 // 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/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-hclog v1.6.3 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-plugin v1.6.1 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // 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.14 // indirect
github.com/klauspost/cpuid/v2 v2.2.3 // indirect
github.com/jmoiron/sqlx v1.4.0 // indirect
github.com/klauspost/compress v1.17.8 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/magiconair/properties v1.8.7 // 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.16 // indirect
github.com/mattermost/squirrel v0.2.0 // indirect
github.com/mattermost/ldap v0.0.0-20231116144001-0f480c025956 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/minio-go/v7 v7.0.45 // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/minio/minio-go/v7 v7.0.70 // 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
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/pborman/uuid v1.2.1 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/philhofer/fwd v1.1.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // 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-20220927061507-ef77025ab5aa // indirect
github.com/rs/xid v1.4.0 // indirect
github.com/segmentio/backo-go v1.0.1 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/spf13/afero v1.8.2 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.53.0 // indirect
github.com/prometheus/procfs v0.15.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rs/xid v1.5.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/segmentio/backo-go v1.1.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/tidwall/gjson v1.14.4 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tidwall/gjson v1.17.1 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tinylib/msgp v1.1.8 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/tinylib/msgp v1.1.9 // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // 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/mod v0.7.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sync v0.1.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
google.golang.org/protobuf v1.28.1 // indirect
github.com/yuin/goldmark v1.7.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20240529005216-23cca8864a10 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
google.golang.org/grpc v1.64.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // 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.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/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
modernc.org/libc v1.50.9 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
modernc.org/sqlite v1.29.10 // indirect
modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect
)

File diff suppressed because it is too large Load Diff

View File

@ -19,8 +19,8 @@ import (
"github.com/mattermost/focalboard/server/services/store/sqlstore"
"github.com/mattermost/focalboard/server/utils"
mmModel "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
mmModel "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/stretchr/testify/require"
)

View File

@ -9,7 +9,7 @@ import (
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/store"
mmModel "github.com/mattermost/mattermost-server/v6/model"
mmModel "github.com/mattermost/mattermost/server/public/model"
)
var errTestStore = errors.New("plugin test store error")

View File

@ -1,55 +0,0 @@
package integrationtests
import (
"testing"
"github.com/mattermost/focalboard/server/client"
"github.com/mattermost/focalboard/server/model"
"github.com/stretchr/testify/require"
)
func TestStatisticsLocalMode(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
t.Run("an unauthenticated client should not be able to get statistics", func(t *testing.T) {
th.Logout(th.Client)
stats, resp := th.Client.GetStatistics()
th.CheckUnauthorized(resp)
require.Nil(t, stats)
})
t.Run("Check authenticated user, not admin", func(t *testing.T) {
th.Login1()
stats, resp := th.Client.GetStatistics()
th.CheckNotImplemented(resp)
require.Nil(t, stats)
})
}
func TestStatisticsPluginMode(t *testing.T) {
th := SetupTestHelperPluginMode(t)
defer th.TearDown()
// Permissions are tested in permissions_test.go
// This tests the functionality.
t.Run("Check authenticated user, admin", func(t *testing.T) {
th.Client = client.NewClient(th.Server.Config().ServerRoot, "")
th.Client.HTTPHeader["Mattermost-User-Id"] = userAdmin
stats, resp := th.Client.GetStatistics()
th.CheckOK(resp)
require.NotNil(t, stats)
numberCards := 2
th.CreateBoardAndCards("testTeam", model.BoardTypeOpen, numberCards)
stats, resp = th.Client.GetStatistics()
th.CheckOK(resp)
require.NotNil(t, stats)
require.Equal(t, 1, stats.Boards)
require.Equal(t, numberCards, stats.Cards)
})
}

View File

@ -3,7 +3,7 @@ package integrationtests
import (
"github.com/mattermost/focalboard/server/services/store"
mmModel "github.com/mattermost/mattermost-server/v6/model"
mmModel "github.com/mattermost/mattermost/server/public/model"
)
type TestStore struct {

View File

@ -16,7 +16,7 @@ import (
"github.com/mattermost/focalboard/server/services/permissions/localpermissions"
)
import (
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
// Active server used with shared code (dll)

View File

@ -5,7 +5,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/mattermost/focalboard/server/utils"

View File

@ -5,7 +5,7 @@ import (
"github.com/mattermost/focalboard/server/utils"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
// GenerateBlockIDs generates new IDs for all the blocks of the list,

View File

@ -1,62 +0,0 @@
package model
import (
"encoding/json"
"io"
mmModel "github.com/mattermost/mattermost-server/v6/model"
)
// BoardInsightsList is a response type with pagination support.
type BoardInsightsList struct {
mmModel.InsightsListData
Items []*BoardInsight `json:"items"`
}
// BoardInsight gives insight into activities in a Board
// swagger:model
type BoardInsight struct {
// ID of the board
// required: true
BoardID string `json:"boardID"`
// icon of the board
// required: false
Icon string `json:"icon"`
// Title of the board
// required: false
Title string `json:"title"`
// Metric of how active the board is
// required: true
ActivityCount string `json:"activityCount"`
// IDs of users active on the board
// required: true
ActiveUsers mmModel.StringArray `json:"activeUsers"`
// ID of user who created the board
// required: true
CreatedBy string `json:"createdBy"`
}
func BoardInsightsFromJSON(data io.Reader) []BoardInsight {
var boardInsights []BoardInsight
_ = json.NewDecoder(data).Decode(&boardInsights)
return boardInsights
}
// GetTopBoardInsightsListWithPagination adds a rank to each item in the given list of BoardInsight and checks if there is
// another page that can be fetched based on the given limit and offset. The given list of BoardInsight is assumed to be
// sorted by ActivityCount(score). Returns a BoardInsightsList.
func GetTopBoardInsightsListWithPagination(boards []*BoardInsight, limit int) *BoardInsightsList {
// Add pagination support
var hasNext bool
if limit != 0 && len(boards) == limit+1 {
hasNext = true
boards = boards[:len(boards)-1]
}
return &BoardInsightsList{InsightsListData: mmModel.InsightsListData{HasNext: hasNext}, Items: boards}
}

View File

@ -8,7 +8,7 @@ import (
"github.com/mattermost/focalboard/server/utils"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
var ErrNoBoardsInBoardsAndBlocks = errors.New("at least one board is required")

View File

@ -5,7 +5,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func TestIsValidBoardsAndBlocks(t *testing.T) {

View File

@ -7,9 +7,9 @@ import (
"net/http"
"strings"
mmModel "github.com/mattermost/mattermost-server/v6/model"
mmModel "github.com/mattermost/mattermost/server/public/model"
pluginapi "github.com/mattermost/mattermost-plugin-api"
pluginapi "github.com/mattermost/mattermost/server/public/pluginapi"
)
var (

View File

@ -8,7 +8,7 @@ import (
"strings"
"github.com/mattermost/focalboard/server/utils"
mm_model "github.com/mattermost/mattermost-server/v6/model"
mm_model "github.com/mattermost/mattermost/server/public/model"
)
func NewFileInfo(name string) *mm_model.FileInfo {

View File

@ -0,0 +1,8 @@
package model
import "github.com/mattermost/logr/v2"
var LvlFBTelemetry = logr.Level{
ID: 9000,
Name: "telemetry",
}

View File

@ -10,8 +10,8 @@ import (
gomock "github.com/golang/mock/gomock"
mux "github.com/gorilla/mux"
model "github.com/mattermost/mattermost-server/v6/model"
mlog "github.com/mattermost/mattermost-server/v6/shared/mlog"
model "github.com/mattermost/mattermost/server/public/model"
mlog "github.com/mattermost/mattermost/server/public/shared/mlog"
)
// MockServicesAPI is a mock of ServicesAPI interface.
@ -141,21 +141,6 @@ func (mr *MockServicesAPIMockRecorder) GetChannelsForTeamForUser(arg0, arg1, arg
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChannelsForTeamForUser", reflect.TypeOf((*MockServicesAPI)(nil).GetChannelsForTeamForUser), arg0, arg1, arg2)
}
// GetCloudLimits mocks base method.
func (m *MockServicesAPI) GetCloudLimits() (*model.ProductLimits, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetCloudLimits")
ret0, _ := ret[0].(*model.ProductLimits)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetCloudLimits indicates an expected call of GetCloudLimits.
func (mr *MockServicesAPIMockRecorder) GetCloudLimits() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCloudLimits", reflect.TypeOf((*MockServicesAPI)(nil).GetCloudLimits))
}
// GetConfig mocks base method.
func (m *MockServicesAPI) GetConfig() *model.Config {
m.ctrl.T.Helper()

View File

@ -3,7 +3,7 @@ package model
import (
"time"
"github.com/mattermost/mattermost-server/v6/utils"
"github.com/mattermost/mattermost/server/v8/channels/utils"
)
// NotificationHint provides a hint that a block has been modified and has subscribers that

View File

@ -1,7 +1,7 @@
package model
import (
mmModel "github.com/mattermost/mattermost-server/v6/model"
mmModel "github.com/mattermost/mattermost/server/public/model"
)
var (

View File

@ -10,8 +10,8 @@ import (
"github.com/gorilla/mux"
mm_model "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
mm_model "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
const (
@ -67,9 +67,6 @@ type ServicesAPI interface {
PublishWebSocketEvent(event string, payload map[string]interface{}, broadcast *mm_model.WebsocketBroadcast)
PublishPluginClusterEvent(ev mm_model.PluginClusterEvent, opts mm_model.PluginClusterEventSendOptions) error
// Cloud service
GetCloudLimits() (*mm_model.ProductLimits, error)
// Config service
GetConfig() *mm_model.Config

Some files were not shown because too many files have changed in this diff Show More