mirror of
https://github.com/mattermost/focalboard.git
synced 2024-12-24 13:43:12 +02:00
Multi product architecture (#3309)
* skeleton lifecycle * bare minimum to satisfy mm-server import * added boards_imports.go * move boards_imports.go to correct package * bump mmserver version; remove replace in go.mod; use module workspaces; remove logger service * rename product.go --> boards.go * add FileInfoStore and Cloud services for product; create minimal pluginAPI interfaces for all packages * rename Boards -> BoardsProduct * compile success * remove hooks service; guard for nil BoardsApp * update to latest mmserver ver * upgrade mmserver to master tip * upgrade mmserver to master tip * bump plugin-api to master tip * fix users service * fix OnActivate crash; normalize AppError returns * fileBackend interface for server/app * feature flag * bump mmserver version * fix linter errors * make go.work when linting * fix go.work creation for CI * add execute flag for script * fix more linter errors * always create a go.work * fix ci go.work * OS agnostic go.work generator * fix path * fix path again * partially disable cypress test * fix case Id --> ID * bump mmserver version * include in go.work for dev * addressed review comments. Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
This commit is contained in:
parent
c16703a04e
commit
605c0079eb
4
.gitignore
vendored
4
.gitignore
vendored
@ -18,6 +18,10 @@ pids
|
||||
.vscode
|
||||
*.code-workspace
|
||||
|
||||
# golang
|
||||
go.work
|
||||
go.work.sum
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
|
5
Makefile
5
Makefile
@ -39,7 +39,10 @@ prebuild: ## Run prebuild actions (install dependencies etc.).
|
||||
|
||||
ci: webapp-ci server-test ## Simulate CI, locally.
|
||||
|
||||
templates-archive: ## Build templates archive file
|
||||
setup-go-work: ## Sets up a go.work file
|
||||
go run ./mattermost-plugin/build/gowork/main.go
|
||||
|
||||
templates-archive: setup-go-work ## Build templates archive file
|
||||
cd server/assets/build-template-archive; go run -tags '$(BUILD_TAGS)' main.go --dir="../templates-boardarchive" --out="../templates.boardarchive"
|
||||
|
||||
server: templates-archive ## Build server for local environment.
|
||||
|
40
linux/go.mod
40
linux/go.mod
@ -4,12 +4,10 @@ go 1.18
|
||||
|
||||
replace github.com/mattermost/focalboard/server => ../server
|
||||
|
||||
replace github.com/mattermost/mattermost-server/v6 => github.com/mattermost/mattermost-server/v6 v6.0.0-20220601144141-e54977931ccd
|
||||
|
||||
require (
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/mattermost/focalboard/server v0.0.0-00010101000000-000000000000
|
||||
github.com/mattermost/mattermost-server/v6 v6.3.0
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220711175838-7ee7523729e6
|
||||
github.com/webview/webview v0.0.0-20220314230258-a2b7746141c3
|
||||
)
|
||||
|
||||
@ -17,7 +15,6 @@ require (
|
||||
github.com/Masterminds/squirrel v1.5.2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
@ -31,33 +28,29 @@ require (
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/graph-gophers/graphql-go v1.4.0 // indirect
|
||||
github.com/hashicorp/go-hclog v1.2.0 // indirect
|
||||
github.com/hashicorp/go-plugin v1.4.4 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // 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.3 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.12 // indirect
|
||||
github.com/klauspost/compress v1.15.6 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.13 // 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.5 // indirect
|
||||
github.com/lib/pq v1.10.6 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 // indirect
|
||||
github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d // indirect
|
||||
github.com/mattermost/logr/v2 v2.0.15 // indirect
|
||||
github.com/mattermost/mattermost-plugin-api v0.0.27 // indirect
|
||||
github.com/mattermost/mattermost-plugin-api v0.0.28-0.20220623051512-0afd85e854d4 // indirect
|
||||
github.com/mattermost/morph v0.0.0-20220401091636-39f834798da8 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // 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.26 // indirect
|
||||
github.com/minio/minio-go/v7 v7.0.28 // indirect
|
||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
@ -69,7 +62,7 @@ require (
|
||||
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.32.1 // indirect
|
||||
github.com/prometheus/common v0.33.0 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
github.com/rs/xid v1.4.0 // indirect
|
||||
@ -81,7 +74,7 @@ require (
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.10.1 // indirect
|
||||
github.com/stretchr/testify v1.7.1 // indirect
|
||||
github.com/stretchr/testify v1.7.2 // indirect
|
||||
github.com/subosito/gotenv v1.2.0 // indirect
|
||||
github.com/tidwall/gjson v1.14.1 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
@ -93,20 +86,17 @@ require (
|
||||
github.com/wiggin77/srslog v1.0.1 // indirect
|
||||
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect
|
||||
github.com/yuin/goldmark v1.4.12 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // 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/tools v0.1.10 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect
|
||||
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3 // indirect
|
||||
google.golang.org/grpc v1.46.0 // indirect
|
||||
golang.org/x/tools v0.1.11 // indirect
|
||||
google.golang.org/protobuf v1.28.0 // indirect
|
||||
gopkg.in/ini.v1 v1.66.4 // indirect
|
||||
gopkg.in/ini.v1 v1.66.6 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lukechampine.com/uint128 v1.2.0 // indirect
|
||||
modernc.org/cc/v3 v3.35.24 // indirect
|
||||
modernc.org/ccgo/v3 v3.15.17 // indirect
|
||||
|
95
linux/go.sum
95
linux/go.sum
@ -130,6 +130,7 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/RoaringBitmap/roaring v0.9.4/go.mod h1:icnadbWcNyfEHlYdr+tDlOTih1Bf/h+rzPpv4sbomAA=
|
||||
github.com/RoaringBitmap/roaring v1.2.1/go.mod h1:icnadbWcNyfEHlYdr+tDlOTih1Bf/h+rzPpv4sbomAA=
|
||||
github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
|
||||
github.com/advancedlogic/GoOse v0.0.0-20191112112754-e742535969c1/go.mod h1:f3HCSN1fBWjcpGtXyM119MJgeQl838v6so/PQOqvE1w=
|
||||
@ -164,7 +165,7 @@ github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:l
|
||||
github.com/avct/uasurfer v0.0.0-20191028135549-26b5daa857f1/go.mod h1:noBAuukeYOXa0aXGqxr24tADqkwDO2KRD15FsuaZ5a8=
|
||||
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
|
||||
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.44.9/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go v1.44.34/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go-v2 v1.8.0/go.mod h1:xEFuWz+3TYdlPRuo+CqATbeDWIWyaT5uAPwPaWtgse0=
|
||||
github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.6.0/go.mod h1:TNtBVmka80lRPk5+S9ZqVfFszOQAGJJ9KbT3EM3CHNU=
|
||||
@ -210,27 +211,34 @@ github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqO
|
||||
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
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/blevesearch/bleve/v2 v2.3.2/go.mod h1:96+xE5pZUOsr3Y4vHzV1cBC837xZCpwLlX0hrrxnvIg=
|
||||
github.com/blevesearch/bleve_index_api v1.0.1/go.mod h1:fiwKS0xLEm+gBRgv5mumf0dhgFr2mDgZah1pqv1c1M4=
|
||||
github.com/blevesearch/bleve_index_api v1.0.2/go.mod h1:fiwKS0xLEm+gBRgv5mumf0dhgFr2mDgZah1pqv1c1M4=
|
||||
github.com/blevesearch/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:9eJDeqxJ3E7WnLebQUlPD7ZjSce7AnDb9vjGmMCbD0A=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
|
||||
github.com/blevesearch/goleveldb v1.0.1/go.mod h1:WrU8ltZbIp0wAoig/MHbrPCXSOLpe79nz5lv5nqfYrQ=
|
||||
github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk=
|
||||
github.com/blevesearch/mmap-go v1.0.2/go.mod h1:ol2qBqYaOUsGdm7aRMRrYGgPvnwLe6Y+7LMvAB5IbSA=
|
||||
github.com/blevesearch/mmap-go v1.0.3/go.mod h1:pYvKl/grLQrBxuaRYgoTssa4rVujYYeenDp++2E+yvs=
|
||||
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.1.0/go.mod h1:uch7xyyO/Alxkuxa+CGs79vw0QY8BENSBjg6Mw5L5DE=
|
||||
github.com/blevesearch/segment v0.9.0/go.mod h1:9PfHYUdQCgHktBgvtUOF4x+pc4/l8rdH0u5spnW85UQ=
|
||||
github.com/blevesearch/snowball v0.6.1/go.mod h1:ZF0IBg5vgpeoUhnMza2v0A/z8m1cWPlwhke08LpNusg=
|
||||
github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs=
|
||||
github.com/blevesearch/upsidedown_store_api v1.0.1/go.mod h1:MQDVGpHZrpe3Uy26zJBf/a8h0FZY6xJbthIMm8myH2Q=
|
||||
github.com/blevesearch/vellum v1.0.7/go.mod h1:doBZpmRhwTsASB4QdUZANlJvqVAUdUyX0ZK7QJCTeBE=
|
||||
github.com/blevesearch/vellum v1.0.8/go.mod h1:+cpRi/tqq49xUYSQN2P7A5zNSNrS+MscLeeaZ3J46UA=
|
||||
github.com/blevesearch/zapx/v11 v11.3.3/go.mod h1:YzTfUm4kS3e8OmTXDHVV8OzC5MWPO/VPJZQgPNVb4Lc=
|
||||
github.com/blevesearch/zapx/v11 v11.3.4/go.mod h1:HJ7qdfBxdziuymKvXbsBVhCK5pB98tdzQbc8pJV6tJo=
|
||||
github.com/blevesearch/zapx/v12 v12.3.3/go.mod h1:RMl6lOZqF+sTxKvhQDJ5yK2LT3Mu7E2p/jGdjAaiRxs=
|
||||
github.com/blevesearch/zapx/v12 v12.3.4/go.mod h1:uQrKrK9XjXAAsJfAIE8ViLqIKP/keA2DQhS1XXpjkwA=
|
||||
github.com/blevesearch/zapx/v13 v13.3.3/go.mod h1:eppobNM35U4C22yDvTuxV9xPqo10pwfP/jugL4INWG4=
|
||||
github.com/blevesearch/zapx/v13 v13.3.4/go.mod h1:Wl7hO1gT+IDvJb7i06g2iW5Qvw0KzncJPsBx7WGWhLA=
|
||||
github.com/blevesearch/zapx/v14 v14.3.3/go.mod h1:zXNcVzukh0AvG57oUtT1T0ndi09H0kELNaNmekEy0jw=
|
||||
github.com/blevesearch/zapx/v14 v14.3.4/go.mod h1:b1YhRXXhAj9i+9aOwhRKCHUmJyYieK/QbDvPJDLddUk=
|
||||
github.com/blevesearch/zapx/v15 v15.3.3/go.mod h1:C+f/97ZzTzK6vt/7sVlZdzZxKu+5+j4SrGCvr9dJzaY=
|
||||
github.com/blevesearch/zapx/v15 v15.3.4/go.mod h1:TQ/qDC2q7TSSpeC6Vgr9fDN56Ra0u49lZJQ4v30WEx4=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
@ -526,10 +534,12 @@ github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3I
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||
github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
@ -767,8 +777,8 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM=
|
||||
github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw=
|
||||
github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
|
||||
@ -861,7 +871,6 @@ github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0/go.mod h1:CVKl
|
||||
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
|
||||
github.com/jaytaylor/html2text v0.0.0-20211105163654-bc68cce691ba/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
|
||||
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
@ -920,16 +929,16 @@ github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8
|
||||
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.3 h1:wmfu2iqj9q22SyMINp1uQ8C2/V4M1phJdmH9fG4nba0=
|
||||
github.com/klauspost/compress v1.15.3/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY=
|
||||
github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
|
||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.0.13 h1:1XxvOiqXZ8SULZUKim/wncr3wZ38H4yCuVDvKdK9OGs=
|
||||
github.com/klauspost/cpuid/v2 v2.0.13/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@ -966,9 +975,8 @@ github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.5 h1:J+gdV2cUmX7ZqL2B0lFcW0m+egaHC2V3lpO8nWxyYiQ=
|
||||
github.com/lib/pq v1.10.5/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs=
|
||||
github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
|
||||
@ -994,10 +1002,11 @@ github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d h1:/RJ/UV7M5c7L2TQ
|
||||
github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d/go.mod h1:HLbgMEI5K131jpxGazJ97AxfPDt31osq36YS1oxFQPQ=
|
||||
github.com/mattermost/logr/v2 v2.0.15 h1:+WNbGcsc3dBao65eXlceB6dTILNJRIrvubnsTl3zBew=
|
||||
github.com/mattermost/logr/v2 v2.0.15/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg=
|
||||
github.com/mattermost/mattermost-plugin-api v0.0.27 h1:zFKQ6JW1/f0MfR5dP9P2umNNYVcLtTO74mM/PrVPNC4=
|
||||
github.com/mattermost/mattermost-plugin-api v0.0.27/go.mod h1:MM+tZ+36Obm9jqcveoxY2RFbwLaZKZUgR1zUlc0UBYw=
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220601144141-e54977931ccd h1:Aio3uqGOhAUZKrsQqdtFHxlJ8EgRmsssy1FxOZIS3vk=
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220601144141-e54977931ccd/go.mod h1:HBSu5YC0k8TLb+7DFFB9/63/+oBZj7pgx8K07lHmzyI=
|
||||
github.com/mattermost/mattermost-plugin-api v0.0.28-0.20220623051512-0afd85e854d4 h1:TF1yBBsLntuNb3wc3DRg30S9i6tv1JwtREtXd7Gnv9E=
|
||||
github.com/mattermost/mattermost-plugin-api v0.0.28-0.20220623051512-0afd85e854d4/go.mod h1:jtiaM6selJi1Od1zGZDGO78hZyG0gI4/I2/8mza4OZg=
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220622145221-00016e3a4ff4/go.mod h1:e2CtTtnty6oH8CiHm40cMOqJ+dJeWEK39/tobCkeMAk=
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220711175838-7ee7523729e6 h1:lfkO5s/ZwuD2esAHGX+0EtmcsAVXJ0S5Xn37uWW/WoQ=
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220711175838-7ee7523729e6/go.mod h1:e2CtTtnty6oH8CiHm40cMOqJ+dJeWEK39/tobCkeMAk=
|
||||
github.com/mattermost/morph v0.0.0-20220401091636-39f834798da8 h1:gwliVjCTqAC01mSCNqa5nJ/4MmGq50vrjsottIhQ4d8=
|
||||
github.com/mattermost/morph v0.0.0-20220401091636-39f834798da8/go.mod h1:jxM3g1bx+k2Thz7jofcHguBS8TZn5Pc+o5MGmORObhw=
|
||||
github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0/go.mod h1:nV5bfVpT//+B1RPD2JvRnxbkLmJEYXmRaaVl15fsXjs=
|
||||
@ -1053,8 +1062,8 @@ github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WT
|
||||
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
|
||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.26 h1:D0HK+8793etZfRY/vHhDmFaP+vmT41K3K4JV9vmZCBQ=
|
||||
github.com/minio/minio-go/v7 v7.0.26/go.mod h1:x81+AX5gHSfCSqw7jxRKHvxUXMlE5uKX0Vb75Xk5yYg=
|
||||
github.com/minio/minio-go/v7 v7.0.28 h1:VMr3K5qGIEt+/KW3poopRh8mzi5RwuCjmrmstK196Fg=
|
||||
github.com/minio/minio-go/v7 v7.0.28/go.mod h1:x81+AX5gHSfCSqw7jxRKHvxUXMlE5uKX0Vb75Xk5yYg=
|
||||
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
|
||||
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
|
||||
@ -1254,8 +1263,9 @@ github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
|
||||
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/common v0.33.0 h1:rHgav/0a6+uYgGdNt3jwz8FNSesO/Hsang3O0T9A5SE=
|
||||
github.com/prometheus/common v0.33.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE=
|
||||
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
@ -1295,7 +1305,6 @@ github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
|
||||
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
github.com/rudderlabs/analytics-go v3.3.1+incompatible/go.mod h1:LF8/ty9kUX4PTY3l5c97K3nZZaX5Hwsvt+NBaRL/f30=
|
||||
github.com/rudderlabs/analytics-go v3.3.2+incompatible h1:bDajEJTYhfHjNYxbQFMA/2dHlOjyeSgxS7GPIdMZ52Q=
|
||||
github.com/rudderlabs/analytics-go v3.3.2+incompatible/go.mod h1:LF8/ty9kUX4PTY3l5c97K3nZZaX5Hwsvt+NBaRL/f30=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
@ -1418,8 +1427,9 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
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 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||
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/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
@ -1608,8 +1618,8 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 h1:NvGWuYG8dkDHFSKksI1P9faiVJ9rayE6l0+ouWVIDs8=
|
||||
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
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/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@ -1635,7 +1645,7 @@ golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+o
|
||||
golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
||||
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=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
@ -1662,8 +1672,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -1742,8 +1752,8 @@ golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/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/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@ -1765,6 +1775,7 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ
|
||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -1778,6 +1789,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -1910,8 +1922,10 @@ golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 h1:PgOr27OhUx2IRqGJ2RxAWI4dJQ7bi9cSrB82uzFzfUA=
|
||||
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
@ -2021,16 +2035,16 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20=
|
||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||
golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
|
||||
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U=
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0=
|
||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
||||
gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
|
||||
gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0=
|
||||
@ -2161,8 +2175,8 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6
|
||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
||||
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3 h1:q1kiSVscqoDeqTF27eQ2NnLLDmqF0I373qQNXYMy0fo=
|
||||
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||
google.golang.org/genproto v0.0.0-20220614165028-45ed7f3ff16e h1:ubR4JUtqN3ffdFjpKylv8scWk/mZstGmzXbgYSkuMl0=
|
||||
google.golang.org/genproto v0.0.0-20220614165028-45ed7f3ff16e/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
@ -2200,8 +2214,8 @@ google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K
|
||||
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||
google.golang.org/grpc v1.46.0 h1:oCjezcn6g6A75TGoKYBPgKmVBLexhYLM6MebdrPApP8=
|
||||
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
|
||||
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
@ -2238,8 +2252,8 @@ gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4=
|
||||
gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI=
|
||||
gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
@ -2264,8 +2278,9 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/postgres v1.0.8/go.mod h1:4eOzrI1MUfm6ObJU/UcmbXyiHSs8jSwH95G5P5dxcAg=
|
||||
gorm.io/gorm v1.20.12/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
gorm.io/gorm v1.21.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
|
@ -60,6 +60,9 @@ all: check-style test dist
|
||||
apply:
|
||||
./build/bin/manifest apply
|
||||
|
||||
setup-go-work: ## Sets up a go.work file
|
||||
cd ..; go run ./mattermost-plugin/build/gowork/main.go
|
||||
|
||||
## Runs eslint and golangci-lint
|
||||
.PHONY: check-style
|
||||
check-style: webapp/node_modules
|
||||
@ -80,7 +83,7 @@ ifneq ($(HAS_SERVER),)
|
||||
golangci-lint run ./...
|
||||
endif
|
||||
|
||||
templates-archive: ## Build templates archive file
|
||||
templates-archive: setup-go-work ## Build templates archive file
|
||||
cd ../server/assets/build-template-archive; go run -tags '$(BUILD_TAGS)' main.go --dir="../templates-boardarchive" --out="../templates.boardarchive"
|
||||
|
||||
## Builds the server, if it exists, for all supported architectures.
|
||||
|
@ -2,13 +2,11 @@ module github.com/mattermost/mattermost-plugin-starter-template/build
|
||||
|
||||
go 1.18
|
||||
|
||||
replace github.com/mattermost/mattermost-server/v6 => github.com/mattermost/mattermost-server/v6 v6.0.0-20220601144141-e54977931ccd
|
||||
|
||||
require (
|
||||
github.com/go-git/go-git/v5 v5.1.0
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220601144141-e54977931ccd
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220705131644-b99bd0d04915
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/stretchr/testify v1.7.1
|
||||
github.com/stretchr/testify v1.7.2
|
||||
sigs.k8s.io/yaml v1.2.0
|
||||
)
|
||||
|
||||
@ -25,17 +23,17 @@ require (
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/graph-gophers/graphql-go v1.4.0 // indirect
|
||||
github.com/imdario/mergo v0.3.9 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect
|
||||
github.com/klauspost/compress v1.15.3 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.12 // indirect
|
||||
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/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/minio/minio-go/v7 v7.0.26 // indirect
|
||||
github.com/minio/minio-go/v7 v7.0.28 // indirect
|
||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
@ -53,13 +51,13 @@ require (
|
||||
github.com/wiggin77/merror v1.0.3 // 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-20220507011949-2cf3adece122 // indirect
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // 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
|
||||
gopkg.in/ini.v1 v1.66.4 // indirect
|
||||
gopkg.in/ini.v1 v1.66.6 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
@ -84,8 +84,9 @@ github.com/graph-gophers/graphql-go v1.4.0 h1:JE9wveRTSXwJyjdRd6bOQ7Ob5bewTUQ58J
|
||||
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/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
|
||||
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=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
@ -97,12 +98,12 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.15.3 h1:wmfu2iqj9q22SyMINp1uQ8C2/V4M1phJdmH9fG4nba0=
|
||||
github.com/klauspost/compress v1.15.3/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY=
|
||||
github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.0.13 h1:1XxvOiqXZ8SULZUKim/wncr3wZ38H4yCuVDvKdK9OGs=
|
||||
github.com/klauspost/cpuid/v2 v2.0.13/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
@ -117,14 +118,14 @@ github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d h1:/RJ/UV7M5c7L2TQ
|
||||
github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d/go.mod h1:HLbgMEI5K131jpxGazJ97AxfPDt31osq36YS1oxFQPQ=
|
||||
github.com/mattermost/logr/v2 v2.0.15 h1:+WNbGcsc3dBao65eXlceB6dTILNJRIrvubnsTl3zBew=
|
||||
github.com/mattermost/logr/v2 v2.0.15/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg=
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220601144141-e54977931ccd h1:Aio3uqGOhAUZKrsQqdtFHxlJ8EgRmsssy1FxOZIS3vk=
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220601144141-e54977931ccd/go.mod h1:HBSu5YC0k8TLb+7DFFB9/63/+oBZj7pgx8K07lHmzyI=
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220705131644-b99bd0d04915 h1:W7y+l87t0qORLQMFXtz/s9rxftWZDop8Es6wYQLr5vk=
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220705131644-b99bd0d04915/go.mod h1:e2CtTtnty6oH8CiHm40cMOqJ+dJeWEK39/tobCkeMAk=
|
||||
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=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.26 h1:D0HK+8793etZfRY/vHhDmFaP+vmT41K3K4JV9vmZCBQ=
|
||||
github.com/minio/minio-go/v7 v7.0.26/go.mod h1:x81+AX5gHSfCSqw7jxRKHvxUXMlE5uKX0Vb75Xk5yYg=
|
||||
github.com/minio/minio-go/v7 v7.0.28 h1:VMr3K5qGIEt+/KW3poopRh8mzi5RwuCjmrmstK196Fg=
|
||||
github.com/minio/minio-go/v7 v7.0.28/go.mod h1:x81+AX5gHSfCSqw7jxRKHvxUXMlE5uKX0Vb75Xk5yYg=
|
||||
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
|
||||
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
@ -194,8 +195,9 @@ 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.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||
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/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=
|
||||
@ -226,8 +228,8 @@ golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 h1:NvGWuYG8dkDHFSKksI1P9faiVJ9rayE6l0+ouWVIDs8=
|
||||
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
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/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=
|
||||
@ -245,8 +247,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/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/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=
|
||||
@ -268,8 +270,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/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-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
|
||||
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/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -311,8 +313,8 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4=
|
||||
gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI=
|
||||
gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
@ -321,11 +323,12 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
93
mattermost-plugin/build/gowork/main.go
Normal file
93
mattermost-plugin/build/gowork/main.go
Normal file
@ -0,0 +1,93 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
filename = "go.work"
|
||||
)
|
||||
|
||||
func main() {
|
||||
force := false
|
||||
if len(os.Args) == 2 && strings.ToLower(os.Args[1]) == "-f" {
|
||||
force = true
|
||||
}
|
||||
|
||||
if _, err := os.Stat(filename); err == nil && !force {
|
||||
// go.work already exists and force flag not specified
|
||||
fmt.Fprintln(os.Stdout, "go.work already exists and -f (force) not specified; nothing to do.")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error creating %s: %s", filename, err.Error())
|
||||
os.Exit(-1)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
isCI := isCI()
|
||||
content := makeGoWork(isCI)
|
||||
|
||||
_, err = f.WriteString(content)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error writing %s: %s", filename, err.Error())
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stdout, "go.work written successfully.")
|
||||
}
|
||||
|
||||
func makeGoWork(ci bool) string {
|
||||
var b strings.Builder
|
||||
|
||||
b.WriteString("go 1.18\n\n")
|
||||
b.WriteString("use ./mattermost-plugin\n")
|
||||
b.WriteString("use ./server\n")
|
||||
|
||||
if ci {
|
||||
b.WriteString("use ./linux\n")
|
||||
} else {
|
||||
b.WriteString("use ../mattermost-server\n")
|
||||
b.WriteString("use ../enterprise\n")
|
||||
}
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func isCI() bool {
|
||||
vars := map[string]bool{
|
||||
// var name: must_be_true (false means being defined is enough)
|
||||
"CIRCLECI": true,
|
||||
"GITHUB_ACTIONS": true,
|
||||
"GITLAB_CI": false,
|
||||
"TRAVIS": true,
|
||||
}
|
||||
|
||||
for name, mustBeTrue := range vars {
|
||||
if isEnvVarTrue(name, mustBeTrue) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isEnvVarTrue(name string, mustBeTrue bool) bool {
|
||||
val, ok := os.LookupEnv(name)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if !mustBeTrue {
|
||||
return true
|
||||
}
|
||||
|
||||
switch strings.ToLower(val) {
|
||||
case "t", "1", "true", "y", "yes":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
@ -2,16 +2,10 @@ module github.com/mattermost/focalboard/mattermost-plugin
|
||||
|
||||
go 1.18
|
||||
|
||||
replace github.com/mattermost/focalboard/server => ../server
|
||||
|
||||
replace github.com/mattermost/mattermost-server/v6 => github.com/mattermost/mattermost-server/v6 v6.0.0-20220613202234-182ae1234a49
|
||||
|
||||
require (
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/mattermost/focalboard/server v0.0.0-00010101000000-000000000000
|
||||
github.com/mattermost/mattermost-plugin-api v0.0.27
|
||||
github.com/mattermost/mattermost-server/v6 v6.3.0
|
||||
github.com/stretchr/testify v1.7.1
|
||||
github.com/mattermost/mattermost-plugin-api v0.0.28-0.20220623051512-0afd85e854d4
|
||||
github.com/stretchr/testify v1.7.2
|
||||
)
|
||||
|
||||
require (
|
||||
@ -20,33 +14,33 @@ require (
|
||||
github.com/Masterminds/semver/v3 v3.1.1 // indirect
|
||||
github.com/Masterminds/squirrel v1.5.2 // indirect
|
||||
github.com/PuerkitoBio/goquery v1.8.0 // indirect
|
||||
github.com/RoaringBitmap/roaring v0.9.4 // indirect
|
||||
github.com/RoaringBitmap/roaring v1.2.1 // indirect
|
||||
github.com/advancedlogic/GoOse v0.0.0-20210820140952-9d5822d4a625 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.1 // indirect
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de // indirect
|
||||
github.com/avct/uasurfer v0.0.0-20191028135549-26b5daa857f1 // indirect
|
||||
github.com/aws/aws-sdk-go v1.44.9 // indirect
|
||||
github.com/aws/aws-sdk-go v1.44.34 // indirect
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.2.2 // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/blevesearch/bleve/v2 v2.3.2 // indirect
|
||||
github.com/blevesearch/bleve_index_api v1.0.1 // indirect
|
||||
github.com/blevesearch/bleve_index_api v1.0.2 // indirect
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
||||
github.com/blevesearch/gtreap v0.1.1 // indirect
|
||||
github.com/blevesearch/mmap-go v1.0.3 // indirect
|
||||
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.1.0 // indirect
|
||||
github.com/blevesearch/segment v0.9.0 // indirect
|
||||
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
||||
github.com/blevesearch/upsidedown_store_api v1.0.1 // indirect
|
||||
github.com/blevesearch/vellum v1.0.7 // indirect
|
||||
github.com/blevesearch/zapx/v11 v11.3.3 // indirect
|
||||
github.com/blevesearch/zapx/v12 v12.3.3 // indirect
|
||||
github.com/blevesearch/zapx/v13 v13.3.3 // indirect
|
||||
github.com/blevesearch/zapx/v14 v14.3.3 // indirect
|
||||
github.com/blevesearch/zapx/v15 v15.3.3 // indirect
|
||||
github.com/blevesearch/vellum v1.0.8 // indirect
|
||||
github.com/blevesearch/zapx/v11 v11.3.4 // indirect
|
||||
github.com/blevesearch/zapx/v12 v12.3.4 // indirect
|
||||
github.com/blevesearch/zapx/v13 v13.3.4 // indirect
|
||||
github.com/blevesearch/zapx/v14 v14.3.4 // indirect
|
||||
github.com/blevesearch/zapx/v15 v15.3.4 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
|
||||
@ -79,7 +73,7 @@ require (
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/graph-gophers/graphql-go v1.4.0 // indirect
|
||||
github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c // indirect
|
||||
github.com/hashicorp/go-hclog v1.2.0 // indirect
|
||||
github.com/hashicorp/go-hclog v1.2.1 // indirect
|
||||
github.com/hashicorp/go-plugin v1.4.4 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
@ -89,19 +83,20 @@ require (
|
||||
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.3 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.12 // indirect
|
||||
github.com/klauspost/compress v1.15.6 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.13 // indirect
|
||||
github.com/klauspost/pgzip v1.2.5 // 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/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 // indirect
|
||||
github.com/levigross/exp-html v0.0.0-20120902181939-8df60c69a8f5 // indirect
|
||||
github.com/lib/pq v1.10.5 // indirect
|
||||
github.com/lib/pq v1.10.6 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 // indirect
|
||||
github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d // indirect
|
||||
github.com/mattermost/logr/v2 v2.0.15 // indirect
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220711175838-7ee7523729e6 // indirect
|
||||
github.com/mattermost/morph v0.0.0-20220401091636-39f834798da8 // indirect
|
||||
github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0 // indirect
|
||||
github.com/mattermost/squirrel v0.2.0 // indirect
|
||||
@ -113,7 +108,7 @@ require (
|
||||
github.com/mholt/archiver/v3 v3.5.1 // indirect
|
||||
github.com/microcosm-cc/bluemonday v1.0.18 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/minio/minio-go/v7 v7.0.26 // indirect
|
||||
github.com/minio/minio-go/v7 v7.0.28 // indirect
|
||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
@ -177,24 +172,23 @@ require (
|
||||
github.com/yuin/goldmark v1.4.12 // indirect
|
||||
go.etcd.io/bbolt v1.3.6 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 // indirect
|
||||
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
|
||||
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
golang.org/x/net v0.0.0-20220614195744-fb05da6f9022 // indirect
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect
|
||||
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/tools v0.1.10 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect
|
||||
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3 // indirect
|
||||
google.golang.org/grpc v1.46.0 // indirect
|
||||
golang.org/x/tools v0.1.11 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220614165028-45ed7f3ff16e // indirect
|
||||
google.golang.org/grpc v1.47.0 // indirect
|
||||
google.golang.org/protobuf v1.28.0 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/ini.v1 v1.66.4 // indirect
|
||||
gopkg.in/ini.v1 v1.66.6 // indirect
|
||||
gopkg.in/mail.v2 v2.3.1 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lukechampine.com/uint128 v1.2.0 // indirect
|
||||
modernc.org/cc/v3 v3.35.24 // indirect
|
||||
modernc.org/ccgo/v3 v3.15.17 // indirect
|
||||
|
File diff suppressed because it is too large
Load Diff
209
mattermost-plugin/product/api_adapter.go
Normal file
209
mattermost-plugin/product/api_adapter.go
Normal file
@ -0,0 +1,209 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package product
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/app/request"
|
||||
mm_model "github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
)
|
||||
|
||||
// normalizeAppError returns a truly nil error if appErr is nil
|
||||
// See https://golang.org/doc/faq#nil_error for more details.
|
||||
func normalizeAppErr(appErr *mm_model.AppError) error {
|
||||
if appErr == nil {
|
||||
return nil
|
||||
}
|
||||
return appErr
|
||||
}
|
||||
|
||||
// serviceAPIAdapter is an adapter that flattens the APIs provided by suite services so they can
|
||||
// be used as per the Plugin API.
|
||||
// Note: when supporting a plugin build is no longer needed this adapter may be removed as the Boards app
|
||||
// can be modified to use the services in modular fashion.
|
||||
type serviceAPIAdapter struct {
|
||||
api *boardsProduct
|
||||
ctx *request.Context
|
||||
}
|
||||
|
||||
func newServiceAPIAdapter(api *boardsProduct) *serviceAPIAdapter {
|
||||
return &serviceAPIAdapter{
|
||||
api: api,
|
||||
ctx: &request.Context{},
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Channels service.
|
||||
//
|
||||
|
||||
func (a *serviceAPIAdapter) GetDirectChannel(userID1, userID2 string) (*mm_model.Channel, error) {
|
||||
channel, appErr := a.api.channelService.GetDirectChannel(userID1, userID2)
|
||||
return channel, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *serviceAPIAdapter) GetChannelByID(channelID string) (*mm_model.Channel, error) {
|
||||
channel, appErr := a.api.channelService.GetChannelByID(channelID)
|
||||
return channel, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *serviceAPIAdapter) GetChannelMember(channelID string, userID string) (*mm_model.ChannelMember, error) {
|
||||
member, appErr := a.api.channelService.GetChannelMember(channelID, userID)
|
||||
return member, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *serviceAPIAdapter) GetChannelsForTeamForUser(teamID string, userID string, includeDeleted bool) (mm_model.ChannelList, error) {
|
||||
opts := &mm_model.ChannelSearchOpts{
|
||||
IncludeDeleted: includeDeleted,
|
||||
}
|
||||
channels, appErr := a.api.channelService.GetChannelsForTeamForUser(teamID, userID, opts)
|
||||
return channels, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
//
|
||||
// Post service.
|
||||
//
|
||||
|
||||
func (a *serviceAPIAdapter) CreatePost(post *mm_model.Post) (*mm_model.Post, error) {
|
||||
post, appErr := a.api.postService.CreatePost(a.ctx, post)
|
||||
return post, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
//
|
||||
// User service.
|
||||
//
|
||||
|
||||
func (a *serviceAPIAdapter) GetUserByID(userID string) (*mm_model.User, error) {
|
||||
user, appErr := a.api.userService.GetUser(userID)
|
||||
return user, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *serviceAPIAdapter) GetUserByUsername(name string) (*mm_model.User, error) {
|
||||
user, appErr := a.api.userService.GetUserByUsername(name)
|
||||
return user, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *serviceAPIAdapter) GetUserByEmail(email string) (*mm_model.User, error) {
|
||||
user, appErr := a.api.userService.GetUserByEmail(email)
|
||||
return user, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *serviceAPIAdapter) UpdateUser(user *mm_model.User) (*mm_model.User, error) {
|
||||
user, appErr := a.api.userService.UpdateUser(user, true)
|
||||
return user, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *serviceAPIAdapter) GetUsersFromProfiles(options *mm_model.UserGetOptions) ([]*mm_model.User, error) {
|
||||
user, appErr := a.api.userService.GetUsersFromProfiles(options)
|
||||
return user, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
//
|
||||
// Team service.
|
||||
//
|
||||
|
||||
func (a *serviceAPIAdapter) GetTeamMember(teamID string, userID string) (*mm_model.TeamMember, error) {
|
||||
member, appErr := a.api.teamService.GetMember(teamID, userID)
|
||||
return member, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *serviceAPIAdapter) CreateMember(teamID string, userID string) (*mm_model.TeamMember, error) {
|
||||
member, appErr := a.api.teamService.CreateMember(a.ctx, teamID, userID)
|
||||
return member, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
//
|
||||
// Permissions service.
|
||||
//
|
||||
|
||||
func (a *serviceAPIAdapter) HasPermissionToTeam(userID, teamID string, permission *mm_model.Permission) bool {
|
||||
return a.api.permissionsService.HasPermissionToTeam(userID, teamID, permission)
|
||||
}
|
||||
|
||||
func (a *serviceAPIAdapter) HasPermissionToChannel(askingUserID string, channelID string, permission *mm_model.Permission) bool {
|
||||
return a.api.permissionsService.HasPermissionToChannel(askingUserID, channelID, permission)
|
||||
}
|
||||
|
||||
//
|
||||
// Bot service.
|
||||
//
|
||||
func (a *serviceAPIAdapter) EnsureBot(bot *mm_model.Bot) (string, error) {
|
||||
return a.api.botService.EnsureBot(a.ctx, boardsProductID, bot)
|
||||
}
|
||||
|
||||
//
|
||||
// License service.
|
||||
//
|
||||
func (a *serviceAPIAdapter) GetLicense() *mm_model.License {
|
||||
return a.api.licenseService.GetLicense()
|
||||
}
|
||||
|
||||
//
|
||||
// FileInfoStore service.
|
||||
//
|
||||
func (a *serviceAPIAdapter) GetFileInfo(fileID string) (*mm_model.FileInfo, error) {
|
||||
fi, appErr := a.api.fileInfoStoreService.GetFileInfo(fileID)
|
||||
return fi, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
//
|
||||
// Cluster store.
|
||||
//
|
||||
func (a *serviceAPIAdapter) PublishWebSocketEvent(event string, payload map[string]interface{}, broadcast *mm_model.WebsocketBroadcast) {
|
||||
a.api.clusterService.PublishWebSocketEvent(boardsProductID, event, payload, broadcast)
|
||||
}
|
||||
|
||||
func (a *serviceAPIAdapter) PublishPluginClusterEvent(ev mm_model.PluginClusterEvent, opts mm_model.PluginClusterEventSendOptions) error {
|
||||
return a.api.clusterService.PublishPluginClusterEvent(boardsProductID, ev, opts)
|
||||
}
|
||||
|
||||
//
|
||||
// Cloud service.
|
||||
//
|
||||
func (a *serviceAPIAdapter) GetCloudLimits() (*mm_model.ProductLimits, error) {
|
||||
return a.api.cloudService.GetCloudLimits()
|
||||
}
|
||||
|
||||
//
|
||||
// Config service.
|
||||
//
|
||||
func (a *serviceAPIAdapter) GetConfig() *mm_model.Config {
|
||||
return a.api.configService.Config()
|
||||
}
|
||||
|
||||
//
|
||||
// Logger service.
|
||||
//
|
||||
func (a *serviceAPIAdapter) GetLogger() mlog.LoggerIFace {
|
||||
return a.api.logger
|
||||
}
|
||||
|
||||
//
|
||||
// KVStore service.
|
||||
//
|
||||
func (a *serviceAPIAdapter) KVSetWithOptions(key string, value []byte, options mm_model.PluginKVSetOptions) (bool, error) {
|
||||
b, appErr := a.api.kvStoreService.SetPluginKeyWithOptions(boardsProductID, key, value, options)
|
||||
return b, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
//
|
||||
// Store service.
|
||||
//
|
||||
func (a *serviceAPIAdapter) GetMasterDB() (*sql.DB, error) {
|
||||
return a.api.storeService.GetMasterDB(), nil
|
||||
}
|
||||
|
||||
//
|
||||
// System service.
|
||||
//
|
||||
func (a *serviceAPIAdapter) GetDiagnosticID() string {
|
||||
return a.api.systemService.GetDiagnosticId()
|
||||
}
|
||||
|
||||
// Ensure the adapter implements ServicesAPI.
|
||||
var _ model.ServicesAPI = &serviceAPIAdapter{}
|
287
mattermost-plugin/product/boards_product.go
Normal file
287
mattermost-plugin/product/boards_product.go
Normal file
@ -0,0 +1,287 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package product
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/mattermost/focalboard/mattermost-plugin/server/boards"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/app"
|
||||
mm_model "github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/plugin"
|
||||
"github.com/mattermost/mattermost-server/v6/product"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
const (
|
||||
boardsProductName = "boards"
|
||||
boardsProductID = "com.mattermost.boards"
|
||||
)
|
||||
|
||||
var errServiceTypeAssert = errors.New("type assertion failed")
|
||||
|
||||
func init() {
|
||||
app.RegisterProduct("boards", app.ProductManifest{
|
||||
Initializer: newBoardsProduct,
|
||||
Dependencies: map[app.ServiceKey]struct{}{
|
||||
app.TeamKey: {},
|
||||
app.ChannelKey: {},
|
||||
app.UserKey: {},
|
||||
app.PostKey: {},
|
||||
app.BotKey: {},
|
||||
app.ClusterKey: {},
|
||||
app.ConfigKey: {},
|
||||
app.LogKey: {},
|
||||
app.LicenseKey: {},
|
||||
app.FilestoreKey: {},
|
||||
app.FileInfoStoreKey: {},
|
||||
app.RouterKey: {},
|
||||
app.CloudKey: {},
|
||||
app.KVStoreKey: {},
|
||||
app.StoreKey: {},
|
||||
app.SystemKey: {},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
type boardsProduct struct {
|
||||
teamService product.TeamService
|
||||
channelService product.ChannelService
|
||||
userService product.UserService
|
||||
postService product.PostService
|
||||
permissionsService product.PermissionService
|
||||
botService product.BotService
|
||||
clusterService product.ClusterService
|
||||
configService product.ConfigService
|
||||
logger mlog.LoggerIFace
|
||||
licenseService product.LicenseService
|
||||
filestoreService product.FilestoreService
|
||||
fileInfoStoreService product.FileInfoStoreService
|
||||
routerService product.RouterService
|
||||
cloudService product.CloudService
|
||||
kvStoreService product.KVStoreService
|
||||
storeService product.StoreService
|
||||
systemService product.SystemService
|
||||
|
||||
boardsApp *boards.BoardsApp
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func newBoardsProduct(mmServer *app.Server, services map[app.ServiceKey]interface{}) (app.Product, error) {
|
||||
boards := &boardsProduct{}
|
||||
|
||||
for key, service := range services {
|
||||
switch key {
|
||||
case app.TeamKey:
|
||||
teamService, ok := service.(product.TeamService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.teamService = teamService
|
||||
case app.ChannelKey:
|
||||
channelService, ok := service.(product.ChannelService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.channelService = channelService
|
||||
case app.UserKey:
|
||||
userService, ok := service.(product.UserService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.userService = userService
|
||||
case app.PostKey:
|
||||
postService, ok := service.(product.PostService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.postService = postService
|
||||
case app.PermissionsKey:
|
||||
permissionsService, ok := service.(product.PermissionService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.permissionsService = permissionsService
|
||||
case app.BotKey:
|
||||
botService, ok := service.(product.BotService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.botService = botService
|
||||
case app.ClusterKey:
|
||||
clusterService, ok := service.(product.ClusterService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.clusterService = clusterService
|
||||
case app.ConfigKey:
|
||||
configService, ok := service.(product.ConfigService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.configService = configService
|
||||
case app.LogKey:
|
||||
logger, ok := service.(mlog.LoggerIFace)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.logger = logger.With(mlog.String("product", boardsProductName))
|
||||
case app.LicenseKey:
|
||||
licenseService, ok := service.(product.LicenseService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.licenseService = licenseService
|
||||
case app.FilestoreKey:
|
||||
filestoreService, ok := service.(product.FilestoreService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.filestoreService = filestoreService
|
||||
case app.FileInfoStoreKey:
|
||||
fileInfoStoreService, ok := service.(product.FileInfoStoreService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.fileInfoStoreService = fileInfoStoreService
|
||||
case app.RouterKey:
|
||||
routerService, ok := service.(product.RouterService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.routerService = routerService
|
||||
case app.CloudKey:
|
||||
cloudService, ok := service.(product.CloudService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.cloudService = cloudService
|
||||
case app.KVStoreKey:
|
||||
kvStoreService, ok := service.(product.KVStoreService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.kvStoreService = kvStoreService
|
||||
case app.StoreKey:
|
||||
storeService, ok := service.(product.StoreService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.storeService = storeService
|
||||
case app.SystemKey:
|
||||
systemService, ok := service.(product.SystemService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.systemService = systemService
|
||||
case app.HooksKey: // not needed
|
||||
}
|
||||
}
|
||||
return boards, nil
|
||||
}
|
||||
|
||||
func (bp *boardsProduct) Start() error {
|
||||
if !bp.configService.Config().FeatureFlags.BoardsProduct {
|
||||
bp.logger.Info("Boards product disabled via feature flag")
|
||||
return nil
|
||||
}
|
||||
|
||||
bp.logger.Info("Starting boards service")
|
||||
|
||||
adapter := newServiceAPIAdapter(bp)
|
||||
boardsApp, err := boards.NewBoardsApp(adapter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create Boards service: %w", err)
|
||||
}
|
||||
|
||||
bp.boardsApp = boardsApp
|
||||
if err := bp.boardsApp.Start(); err != nil {
|
||||
return fmt.Errorf("failed to start Boards service: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bp *boardsProduct) Stop() error {
|
||||
bp.logger.Info("Stopping boards service")
|
||||
|
||||
if bp.boardsApp == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := bp.boardsApp.Stop(); err != nil {
|
||||
return fmt.Errorf("error while stopping Boards service: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
// These callbacks are called by the suite automatically
|
||||
//
|
||||
|
||||
func (bp *boardsProduct) OnConfigurationChange() error {
|
||||
if bp.boardsApp == nil {
|
||||
return nil
|
||||
}
|
||||
return bp.boardsApp.OnConfigurationChange()
|
||||
}
|
||||
|
||||
func (bp *boardsProduct) OnWebSocketConnect(webConnID, userID string) {
|
||||
if bp.boardsApp == nil {
|
||||
return
|
||||
}
|
||||
bp.boardsApp.OnWebSocketConnect(webConnID, userID)
|
||||
}
|
||||
|
||||
func (bp *boardsProduct) OnWebSocketDisconnect(webConnID, userID string) {
|
||||
if bp.boardsApp == nil {
|
||||
return
|
||||
}
|
||||
bp.boardsApp.OnWebSocketDisconnect(webConnID, userID)
|
||||
}
|
||||
|
||||
func (bp *boardsProduct) WebSocketMessageHasBeenPosted(webConnID, userID string, req *mm_model.WebSocketRequest) {
|
||||
if bp.boardsApp == nil {
|
||||
return
|
||||
}
|
||||
bp.boardsApp.WebSocketMessageHasBeenPosted(webConnID, userID, req)
|
||||
}
|
||||
|
||||
func (bp *boardsProduct) OnPluginClusterEvent(ctx *plugin.Context, ev mm_model.PluginClusterEvent) {
|
||||
if bp.boardsApp == nil {
|
||||
return
|
||||
}
|
||||
bp.boardsApp.OnPluginClusterEvent(ctx, ev)
|
||||
}
|
||||
|
||||
func (bp *boardsProduct) MessageWillBePosted(ctx *plugin.Context, post *mm_model.Post) (*mm_model.Post, string) {
|
||||
if bp.boardsApp == nil {
|
||||
return post, ""
|
||||
}
|
||||
return bp.boardsApp.MessageWillBePosted(ctx, post)
|
||||
}
|
||||
|
||||
func (bp *boardsProduct) MessageWillBeUpdated(ctx *plugin.Context, newPost, oldPost *mm_model.Post) (*mm_model.Post, string) {
|
||||
if bp.boardsApp == nil {
|
||||
return newPost, ""
|
||||
}
|
||||
return bp.boardsApp.MessageWillBeUpdated(ctx, newPost, oldPost)
|
||||
}
|
||||
|
||||
func (bp *boardsProduct) OnCloudLimitsUpdated(limits *mm_model.ProductLimits) {
|
||||
if bp.boardsApp == nil {
|
||||
return
|
||||
}
|
||||
bp.boardsApp.OnCloudLimitsUpdated(limits)
|
||||
}
|
||||
|
||||
func (bp *boardsProduct) RunDataRetention(nowTime, batchSize int64) (int64, error) {
|
||||
if bp.boardsApp == nil {
|
||||
return 0, nil
|
||||
}
|
||||
return bp.boardsApp.RunDataRetention(nowTime, batchSize)
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package product
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/app"
|
||||
"github.com/mattermost/mattermost-server/v6/product"
|
||||
)
|
||||
|
||||
var errServiceTypeAssert = errors.New("type assertion failed")
|
||||
|
||||
func init() {
|
||||
app.RegisterProduct("boards", app.ProductManifest{
|
||||
Initializer: newBoards,
|
||||
Dependencies: map[app.ServiceKey]struct{}{},
|
||||
})
|
||||
}
|
||||
|
||||
type Boards struct {
|
||||
teamService product.TeamService
|
||||
channelService product.ChannelService
|
||||
userService product.UserService
|
||||
postService product.PostService
|
||||
botService product.BotService
|
||||
clusterService product.ClusterService
|
||||
// configService product.ConfigService
|
||||
logService product.LogService
|
||||
licenseService product.LicenseService
|
||||
// filestoreService product.FilestoreService
|
||||
routerService product.RouterService
|
||||
}
|
||||
|
||||
func newBoards(mmServer *app.Server, services map[app.ServiceKey]interface{}) (app.Product, error) {
|
||||
boards := &Boards{}
|
||||
|
||||
for key, service := range services {
|
||||
switch key {
|
||||
case app.TeamKey:
|
||||
teamService, ok := service.(product.TeamService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.teamService = teamService
|
||||
case app.ChannelKey:
|
||||
channelService, ok := service.(product.ChannelService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.channelService = channelService
|
||||
case app.UserKey:
|
||||
userService, ok := service.(product.UserService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.userService = userService
|
||||
case app.PostKey:
|
||||
postService, ok := service.(product.PostService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.postService = postService
|
||||
case app.BotKey:
|
||||
botService, ok := service.(product.BotService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.botService = botService
|
||||
case app.ClusterKey:
|
||||
clusterService, ok := service.(product.ClusterService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.clusterService = clusterService
|
||||
case app.ConfigKey:
|
||||
// TODO
|
||||
case app.LogKey:
|
||||
logService, ok := service.(product.LogService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.logService = logService
|
||||
case app.LicenseKey:
|
||||
licenseService, ok := service.(product.LicenseService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.licenseService = licenseService
|
||||
case app.FilestoreKey:
|
||||
// TODO
|
||||
case app.RouterKey:
|
||||
routerService, ok := service.(product.RouterService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
||||
}
|
||||
boards.routerService = routerService
|
||||
case app.HooksKey, app.PermissionsKey:
|
||||
// not needed
|
||||
}
|
||||
}
|
||||
return boards, nil
|
||||
}
|
||||
|
||||
func (b *Boards) Start() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Boards) Stop() error {
|
||||
return nil
|
||||
}
|
212
mattermost-plugin/server/api_adapter.go
Normal file
212
mattermost-plugin/server/api_adapter.go
Normal file
@ -0,0 +1,212 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/plugin"
|
||||
|
||||
mm_model "github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
type storeService interface {
|
||||
GetMasterDB() (*sql.DB, error)
|
||||
}
|
||||
|
||||
// normalizeAppError returns a truly nil error if appErr is nil
|
||||
// See https://golang.org/doc/faq#nil_error for more details.
|
||||
func normalizeAppErr(appErr *mm_model.AppError) error {
|
||||
if appErr == nil {
|
||||
return nil
|
||||
}
|
||||
return appErr
|
||||
}
|
||||
|
||||
// pluginAPIAdapter is an adapter that ensures all Plugin API methods have the same signature as the
|
||||
// services API.
|
||||
// Note: this will be removed when plugin builds are no longer needed.
|
||||
type pluginAPIAdapter struct {
|
||||
api plugin.API
|
||||
storeService storeService
|
||||
logger mlog.LoggerIFace
|
||||
}
|
||||
|
||||
func newServiceAPIAdapter(api plugin.API, storeService storeService, logger mlog.LoggerIFace) *pluginAPIAdapter {
|
||||
return &pluginAPIAdapter{
|
||||
api: api,
|
||||
storeService: storeService,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Channels service.
|
||||
//
|
||||
|
||||
func (a *pluginAPIAdapter) GetDirectChannel(userID1, userID2 string) (*mm_model.Channel, error) {
|
||||
channel, appErr := a.api.GetDirectChannel(userID1, userID2)
|
||||
return channel, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *pluginAPIAdapter) GetChannelByID(channelID string) (*mm_model.Channel, error) {
|
||||
channel, appErr := a.api.GetChannel(channelID)
|
||||
return channel, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *pluginAPIAdapter) GetChannelMember(channelID string, userID string) (*mm_model.ChannelMember, error) {
|
||||
member, appErr := a.api.GetChannelMember(channelID, userID)
|
||||
return member, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *pluginAPIAdapter) GetChannelsForTeamForUser(teamID string, userID string, includeDeleted bool) (mm_model.ChannelList, error) {
|
||||
channels, appErr := a.api.GetChannelsForTeamForUser(teamID, userID, includeDeleted)
|
||||
return channels, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
//
|
||||
// Post service.
|
||||
//
|
||||
|
||||
func (a *pluginAPIAdapter) CreatePost(post *mm_model.Post) (*mm_model.Post, error) {
|
||||
post, appErr := a.api.CreatePost(post)
|
||||
return post, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
//
|
||||
// User service.
|
||||
//
|
||||
|
||||
func (a *pluginAPIAdapter) GetUserByID(userID string) (*mm_model.User, error) {
|
||||
user, appErr := a.api.GetUser(userID)
|
||||
return user, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *pluginAPIAdapter) GetUserByUsername(name string) (*mm_model.User, error) {
|
||||
user, appErr := a.api.GetUserByUsername(name)
|
||||
return user, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *pluginAPIAdapter) GetUserByEmail(email string) (*mm_model.User, error) {
|
||||
user, appErr := a.api.GetUserByEmail(email)
|
||||
return user, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *pluginAPIAdapter) UpdateUser(user *mm_model.User) (*mm_model.User, error) {
|
||||
user, appErr := a.api.UpdateUser(user)
|
||||
return user, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *pluginAPIAdapter) GetUsersFromProfiles(options *mm_model.UserGetOptions) ([]*mm_model.User, error) {
|
||||
users, appErr := a.api.GetUsers(options)
|
||||
return users, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
//
|
||||
// Team service.
|
||||
//
|
||||
|
||||
func (a *pluginAPIAdapter) GetTeamMember(teamID string, userID string) (*mm_model.TeamMember, error) {
|
||||
member, appErr := a.api.GetTeamMember(teamID, userID)
|
||||
return member, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
func (a *pluginAPIAdapter) CreateMember(teamID string, userID string) (*mm_model.TeamMember, error) {
|
||||
member, appErr := a.api.CreateTeamMember(teamID, userID)
|
||||
return member, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
//
|
||||
// Permissions service.
|
||||
//
|
||||
|
||||
func (a *pluginAPIAdapter) HasPermissionToTeam(userID, teamID string, permission *mm_model.Permission) bool {
|
||||
return a.api.HasPermissionToTeam(userID, teamID, permission)
|
||||
}
|
||||
|
||||
func (a *pluginAPIAdapter) HasPermissionToChannel(askingUserID string, channelID string, permission *mm_model.Permission) bool {
|
||||
return a.api.HasPermissionToChannel(askingUserID, channelID, permission)
|
||||
}
|
||||
|
||||
//
|
||||
// Bot service.
|
||||
//
|
||||
func (a *pluginAPIAdapter) EnsureBot(bot *mm_model.Bot) (string, error) {
|
||||
return a.api.EnsureBotUser(bot)
|
||||
}
|
||||
|
||||
//
|
||||
// License service.
|
||||
//
|
||||
func (a *pluginAPIAdapter) GetLicense() *mm_model.License {
|
||||
return a.api.GetLicense()
|
||||
}
|
||||
|
||||
//
|
||||
// FileInfoStore service.
|
||||
//
|
||||
func (a *pluginAPIAdapter) GetFileInfo(fileID string) (*mm_model.FileInfo, error) {
|
||||
fi, appErr := a.api.GetFileInfo(fileID)
|
||||
return fi, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
//
|
||||
// Cluster store.
|
||||
//
|
||||
func (a *pluginAPIAdapter) PublishWebSocketEvent(event string, payload map[string]interface{}, broadcast *mm_model.WebsocketBroadcast) {
|
||||
a.api.PublishWebSocketEvent(event, payload, broadcast)
|
||||
}
|
||||
|
||||
func (a *pluginAPIAdapter) PublishPluginClusterEvent(ev mm_model.PluginClusterEvent, opts mm_model.PluginClusterEventSendOptions) error {
|
||||
return a.api.PublishPluginClusterEvent(ev, opts)
|
||||
}
|
||||
|
||||
//
|
||||
// Cloud service.
|
||||
//
|
||||
func (a *pluginAPIAdapter) GetCloudLimits() (*mm_model.ProductLimits, error) {
|
||||
return a.api.GetCloudLimits()
|
||||
}
|
||||
|
||||
//
|
||||
// Config service.
|
||||
//
|
||||
func (a *pluginAPIAdapter) GetConfig() *mm_model.Config {
|
||||
return a.api.GetUnsanitizedConfig()
|
||||
}
|
||||
|
||||
//
|
||||
// Logger service.
|
||||
//
|
||||
func (a *pluginAPIAdapter) GetLogger() mlog.LoggerIFace {
|
||||
return a.logger
|
||||
}
|
||||
|
||||
//
|
||||
// KVStore service.
|
||||
//
|
||||
func (a *pluginAPIAdapter) KVSetWithOptions(key string, value []byte, options mm_model.PluginKVSetOptions) (bool, error) {
|
||||
b, appErr := a.api.KVSetWithOptions(key, value, options)
|
||||
return b, normalizeAppErr(appErr)
|
||||
}
|
||||
|
||||
//
|
||||
// Store service.
|
||||
//
|
||||
func (a *pluginAPIAdapter) GetMasterDB() (*sql.DB, error) {
|
||||
return a.storeService.GetMasterDB()
|
||||
}
|
||||
|
||||
//
|
||||
// System service.
|
||||
//
|
||||
func (a *pluginAPIAdapter) GetDiagnosticID() string {
|
||||
return a.api.GetDiagnosticId()
|
||||
}
|
||||
|
||||
// Ensure the adapter implements ServicesAPI.
|
||||
var _ model.ServicesAPI = &pluginAPIAdapter{}
|
218
mattermost-plugin/server/boards/boardsapp.go
Normal file
218
mattermost-plugin/server/boards/boardsapp.go
Normal file
@ -0,0 +1,218 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package boards
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/mattermost/focalboard/server/auth"
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
"github.com/mattermost/focalboard/server/server"
|
||||
"github.com/mattermost/focalboard/server/services/notify"
|
||||
"github.com/mattermost/focalboard/server/services/permissions/mmpermissions"
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
"github.com/mattermost/focalboard/server/services/store/mattermostauthlayer"
|
||||
"github.com/mattermost/focalboard/server/services/store/sqlstore"
|
||||
"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/plugin"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
|
||||
"github.com/mattermost/mattermost-plugin-api/cluster"
|
||||
)
|
||||
|
||||
const (
|
||||
boardsFeatureFlagName = "BoardsFeatureFlags"
|
||||
PluginName = "focalboard"
|
||||
SharedBoardsName = "enablepublicsharedboards"
|
||||
|
||||
notifyFreqCardSecondsKey = "notify_freq_card_seconds"
|
||||
notifyFreqBoardSecondsKey = "notify_freq_board_seconds"
|
||||
)
|
||||
|
||||
type BoardsEmbed struct {
|
||||
OriginalPath string `json:"originalPath"`
|
||||
TeamID string `json:"teamID"`
|
||||
ViewID string `json:"viewID"`
|
||||
BoardID string `json:"boardID"`
|
||||
CardID string `json:"cardID"`
|
||||
ReadToken string `json:"readToken,omitempty"`
|
||||
}
|
||||
|
||||
type BoardsApp struct {
|
||||
// configurationLock synchronizes access to the configuration.
|
||||
configurationLock sync.RWMutex
|
||||
|
||||
// configuration is the active plugin configuration. Consult getConfiguration and
|
||||
// setConfiguration for usage.
|
||||
configuration *configuration
|
||||
|
||||
server *server.Server
|
||||
wsPluginAdapter ws.PluginAdapterInterface
|
||||
|
||||
servicesAPI model.ServicesAPI
|
||||
logger mlog.LoggerIFace
|
||||
}
|
||||
|
||||
func NewBoardsApp(api model.ServicesAPI) (*BoardsApp, error) {
|
||||
mmconfig := api.GetConfig()
|
||||
logger := api.GetLogger()
|
||||
|
||||
baseURL := ""
|
||||
if mmconfig.ServiceSettings.SiteURL != nil {
|
||||
baseURL = *mmconfig.ServiceSettings.SiteURL
|
||||
}
|
||||
serverID := api.GetDiagnosticID()
|
||||
cfg := createBoardsConfig(*mmconfig, baseURL, serverID)
|
||||
sqlDB, err := api.GetMasterDB()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot access database while initializing Boards: %w", err)
|
||||
}
|
||||
|
||||
storeParams := sqlstore.Params{
|
||||
DBType: cfg.DBType,
|
||||
ConnectionString: cfg.DBConfigString,
|
||||
TablePrefix: cfg.DBTablePrefix,
|
||||
Logger: logger,
|
||||
DB: sqlDB,
|
||||
IsPlugin: true,
|
||||
NewMutexFn: func(name string) (*cluster.Mutex, error) {
|
||||
return cluster.NewMutex(&mutexAPIAdapter{api: api}, name)
|
||||
},
|
||||
ServicesAPI: api,
|
||||
}
|
||||
|
||||
var db store.Store
|
||||
db, err = sqlstore.New(storeParams)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error initializing the DB: %w", err)
|
||||
}
|
||||
if cfg.AuthMode == server.MattermostAuthMod {
|
||||
layeredStore, err2 := mattermostauthlayer.New(cfg.DBType, sqlDB, db, logger, api, storeParams.TablePrefix)
|
||||
if err2 != nil {
|
||||
return nil, fmt.Errorf("error initializing the DB: %w", err2)
|
||||
}
|
||||
db = layeredStore
|
||||
}
|
||||
|
||||
permissionsService := mmpermissions.New(db, api, logger)
|
||||
|
||||
wsPluginAdapter := ws.NewPluginAdapter(api, auth.New(cfg, db, permissionsService), db, logger)
|
||||
|
||||
backendParams := notifyBackendParams{
|
||||
cfg: cfg,
|
||||
servicesAPI: api,
|
||||
appAPI: &appAPI{store: db},
|
||||
permissions: permissionsService,
|
||||
serverRoot: baseURL + "/boards",
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
var notifyBackends []notify.Backend
|
||||
|
||||
mentionsBackend, err := createMentionsNotifyBackend(backendParams)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating mention notifications backend: %w", err)
|
||||
}
|
||||
notifyBackends = append(notifyBackends, mentionsBackend)
|
||||
|
||||
subscriptionsBackend, err2 := createSubscriptionsNotifyBackend(backendParams)
|
||||
if err2 != nil {
|
||||
return nil, fmt.Errorf("error creating subscription notifications backend: %w", err2)
|
||||
}
|
||||
notifyBackends = append(notifyBackends, subscriptionsBackend)
|
||||
mentionsBackend.AddListener(subscriptionsBackend)
|
||||
|
||||
params := server.Params{
|
||||
Cfg: cfg,
|
||||
SingleUserToken: "",
|
||||
DBStore: db,
|
||||
Logger: logger,
|
||||
ServerID: serverID,
|
||||
WSAdapter: wsPluginAdapter,
|
||||
NotifyBackends: notifyBackends,
|
||||
PermissionsService: permissionsService,
|
||||
IsPlugin: true,
|
||||
}
|
||||
|
||||
server, err := server.New(params)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error initializing the server: %w", err)
|
||||
}
|
||||
|
||||
backendParams.appAPI.init(db, server.App())
|
||||
|
||||
if utils.IsCloudLicense(api.GetLicense()) {
|
||||
limits, err := api.GetCloudLimits()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching cloud limits when starting Boards: %w", err)
|
||||
}
|
||||
|
||||
if err := server.App().SetCloudLimits(limits); err != nil {
|
||||
return nil, fmt.Errorf("error setting cloud limits when starting Boards: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return &BoardsApp{
|
||||
server: server,
|
||||
wsPluginAdapter: wsPluginAdapter,
|
||||
servicesAPI: api,
|
||||
logger: logger,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *BoardsApp) Start() error {
|
||||
if err := b.server.Start(); err != nil {
|
||||
return fmt.Errorf("error starting Boards server: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BoardsApp) Stop() error {
|
||||
return b.server.Shutdown()
|
||||
}
|
||||
|
||||
//
|
||||
// These callbacks are called automatically by the suite server.
|
||||
//
|
||||
|
||||
func (b *BoardsApp) MessageWillBePosted(_ *plugin.Context, post *mm_model.Post) (*mm_model.Post, string) {
|
||||
return postWithBoardsEmbed(post), ""
|
||||
}
|
||||
|
||||
func (b *BoardsApp) MessageWillBeUpdated(_ *plugin.Context, newPost, _ *mm_model.Post) (*mm_model.Post, string) {
|
||||
return postWithBoardsEmbed(newPost), ""
|
||||
}
|
||||
|
||||
func (b *BoardsApp) OnWebSocketConnect(webConnID, userID string) {
|
||||
b.wsPluginAdapter.OnWebSocketConnect(webConnID, userID)
|
||||
}
|
||||
|
||||
func (b *BoardsApp) OnWebSocketDisconnect(webConnID, userID string) {
|
||||
b.wsPluginAdapter.OnWebSocketDisconnect(webConnID, userID)
|
||||
}
|
||||
|
||||
func (b *BoardsApp) WebSocketMessageHasBeenPosted(webConnID, userID string, req *mm_model.WebSocketRequest) {
|
||||
b.wsPluginAdapter.WebSocketMessageHasBeenPosted(webConnID, userID, req)
|
||||
}
|
||||
|
||||
func (b *BoardsApp) OnPluginClusterEvent(_ *plugin.Context, ev mm_model.PluginClusterEvent) {
|
||||
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()
|
||||
router.ServeHTTP(w, r)
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package main
|
||||
package boards
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
@ -9,40 +9,13 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
func TestServeHTTP(t *testing.T) {
|
||||
th, tearDown := SetupTestHelper(t)
|
||||
defer tearDown()
|
||||
|
||||
assert := assert.New(t)
|
||||
plugin := Plugin{
|
||||
server: th.Server,
|
||||
}
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest(http.MethodGet, "/hello", nil)
|
||||
|
||||
plugin.ServeHTTP(nil, w, r)
|
||||
|
||||
result := w.Result()
|
||||
assert.NotNil(result)
|
||||
defer result.Body.Close()
|
||||
bodyBytes, err := ioutil.ReadAll(result.Body)
|
||||
assert.Nil(err)
|
||||
bodyString := string(bodyBytes)
|
||||
|
||||
assert.Equal("Hello", bodyString)
|
||||
}
|
||||
|
||||
func TestSetConfiguration(t *testing.T) {
|
||||
th, tearDown := SetupTestHelper(t)
|
||||
defer tearDown()
|
||||
|
||||
plugin := Plugin{
|
||||
server: th.Server,
|
||||
}
|
||||
boolTrue := true
|
||||
stringRef := ""
|
||||
|
||||
@ -89,7 +62,7 @@ func TestSetConfiguration(t *testing.T) {
|
||||
mmConfig := baseConfig
|
||||
mmConfig.LogSettings = *logSettings
|
||||
|
||||
config := plugin.createBoardsConfig(*mmConfig, "", "testId")
|
||||
config := createBoardsConfig(*mmConfig, "", "testId")
|
||||
assert.Equal(t, true, config.Telemetry)
|
||||
assert.Equal(t, "testId", config.TelemetryID)
|
||||
})
|
||||
@ -97,9 +70,9 @@ func TestSetConfiguration(t *testing.T) {
|
||||
t.Run("test enable shared boards", func(t *testing.T) {
|
||||
mmConfig := baseConfig
|
||||
mmConfig.PluginSettings.Plugins = make(map[string]map[string]interface{})
|
||||
mmConfig.PluginSettings.Plugins[pluginName] = make(map[string]interface{})
|
||||
mmConfig.PluginSettings.Plugins[pluginName][sharedBoardsName] = true
|
||||
config := plugin.createBoardsConfig(*mmConfig, "", "")
|
||||
mmConfig.PluginSettings.Plugins[PluginName] = make(map[string]interface{})
|
||||
mmConfig.PluginSettings.Plugins[PluginName][SharedBoardsName] = true
|
||||
config := createBoardsConfig(*mmConfig, "", "")
|
||||
assert.Equal(t, true, config.EnablePublicSharedBoards)
|
||||
})
|
||||
|
||||
@ -113,7 +86,7 @@ func TestSetConfiguration(t *testing.T) {
|
||||
mmConfig := baseConfig
|
||||
mmConfig.FeatureFlags = featureFlags
|
||||
|
||||
config := plugin.createBoardsConfig(*mmConfig, "", "")
|
||||
config := createBoardsConfig(*mmConfig, "", "")
|
||||
assert.Equal(t, "true", config.FeatureFlags["TestBoolFeature"])
|
||||
assert.Equal(t, "test", config.FeatureFlags["TestFeature"])
|
||||
|
||||
@ -121,3 +94,28 @@ func TestSetConfiguration(t *testing.T) {
|
||||
assert.Equal(t, "true", config.FeatureFlags["myTest"])
|
||||
})
|
||||
}
|
||||
|
||||
func TestServeHTTP(t *testing.T) {
|
||||
th, tearDown := SetupTestHelper(t)
|
||||
defer tearDown()
|
||||
|
||||
b := &BoardsApp{
|
||||
server: th.Server,
|
||||
logger: mlog.CreateConsoleTestLogger(true, mlog.LvlError),
|
||||
}
|
||||
|
||||
assert := assert.New(t)
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest(http.MethodGet, "/hello", nil)
|
||||
|
||||
b.ServeHTTP(nil, w, r)
|
||||
|
||||
result := w.Result()
|
||||
assert.NotNil(result)
|
||||
defer result.Body.Close()
|
||||
bodyBytes, err := ioutil.ReadAll(result.Body)
|
||||
assert.Nil(err)
|
||||
bodyString := string(bodyBytes)
|
||||
|
||||
assert.Equal("Hello", bodyString)
|
||||
}
|
136
mattermost-plugin/server/boards/boardsapp_util.go
Normal file
136
mattermost-plugin/server/boards/boardsapp_util.go
Normal file
@ -0,0 +1,136 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package boards
|
||||
|
||||
import (
|
||||
"math"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/mattermost/focalboard/server/services/config"
|
||||
|
||||
mm_model "github.com/mattermost/mattermost-server/v6/model"
|
||||
)
|
||||
|
||||
func createBoardsConfig(mmconfig mm_model.Config, baseURL string, serverID string) *config.Configuration {
|
||||
filesS3Config := config.AmazonS3Config{}
|
||||
if mmconfig.FileSettings.AmazonS3AccessKeyId != nil {
|
||||
filesS3Config.AccessKeyID = *mmconfig.FileSettings.AmazonS3AccessKeyId
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3SecretAccessKey != nil {
|
||||
filesS3Config.SecretAccessKey = *mmconfig.FileSettings.AmazonS3SecretAccessKey
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3Bucket != nil {
|
||||
filesS3Config.Bucket = *mmconfig.FileSettings.AmazonS3Bucket
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3PathPrefix != nil {
|
||||
filesS3Config.PathPrefix = *mmconfig.FileSettings.AmazonS3PathPrefix
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3Region != nil {
|
||||
filesS3Config.Region = *mmconfig.FileSettings.AmazonS3Region
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3Endpoint != nil {
|
||||
filesS3Config.Endpoint = *mmconfig.FileSettings.AmazonS3Endpoint
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3SSL != nil {
|
||||
filesS3Config.SSL = *mmconfig.FileSettings.AmazonS3SSL
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3SignV2 != nil {
|
||||
filesS3Config.SignV2 = *mmconfig.FileSettings.AmazonS3SignV2
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3SSE != nil {
|
||||
filesS3Config.SSE = *mmconfig.FileSettings.AmazonS3SSE
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3Trace != nil {
|
||||
filesS3Config.Trace = *mmconfig.FileSettings.AmazonS3Trace
|
||||
}
|
||||
|
||||
enableTelemetry := false
|
||||
if mmconfig.LogSettings.EnableDiagnostics != nil {
|
||||
enableTelemetry = *mmconfig.LogSettings.EnableDiagnostics
|
||||
}
|
||||
|
||||
enablePublicSharedBoards := false
|
||||
if mmconfig.PluginSettings.Plugins[PluginName][SharedBoardsName] == true {
|
||||
enablePublicSharedBoards = true
|
||||
}
|
||||
|
||||
enableBoardsDeletion := false
|
||||
if mmconfig.DataRetentionSettings.EnableBoardsDeletion != nil {
|
||||
enableBoardsDeletion = true
|
||||
}
|
||||
|
||||
featureFlags := parseFeatureFlags(mmconfig.FeatureFlags.ToMap())
|
||||
|
||||
return &config.Configuration{
|
||||
ServerRoot: baseURL + "/plugins/focalboard",
|
||||
Port: -1,
|
||||
DBType: *mmconfig.SqlSettings.DriverName,
|
||||
DBConfigString: *mmconfig.SqlSettings.DataSource,
|
||||
DBTablePrefix: "focalboard_",
|
||||
UseSSL: false,
|
||||
SecureCookie: true,
|
||||
WebPath: path.Join(*mmconfig.PluginSettings.Directory, "focalboard", "pack"),
|
||||
FilesDriver: *mmconfig.FileSettings.DriverName,
|
||||
FilesPath: *mmconfig.FileSettings.Directory,
|
||||
FilesS3Config: filesS3Config,
|
||||
MaxFileSize: *mmconfig.FileSettings.MaxFileSize,
|
||||
Telemetry: enableTelemetry,
|
||||
TelemetryID: serverID,
|
||||
WebhookUpdate: []string{},
|
||||
SessionExpireTime: 2592000,
|
||||
SessionRefreshTime: 18000,
|
||||
LocalOnly: false,
|
||||
EnableLocalMode: false,
|
||||
LocalModeSocketLocation: "",
|
||||
AuthMode: "mattermost",
|
||||
EnablePublicSharedBoards: enablePublicSharedBoards,
|
||||
FeatureFlags: featureFlags,
|
||||
NotifyFreqCardSeconds: getPluginSettingInt(mmconfig, notifyFreqCardSecondsKey, 120),
|
||||
NotifyFreqBoardSeconds: getPluginSettingInt(mmconfig, notifyFreqBoardSecondsKey, 86400),
|
||||
EnableDataRetention: enableBoardsDeletion,
|
||||
DataRetentionDays: *mmconfig.DataRetentionSettings.BoardsRetentionDays,
|
||||
TeammateNameDisplay: *mmconfig.TeamSettings.TeammateNameDisplay,
|
||||
}
|
||||
}
|
||||
|
||||
func getPluginSetting(mmConfig mm_model.Config, key string) (interface{}, bool) {
|
||||
plugin, ok := mmConfig.PluginSettings.Plugins[PluginName]
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
val, ok := plugin[key]
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
return val, true
|
||||
}
|
||||
|
||||
func getPluginSettingInt(mmConfig mm_model.Config, key string, def int) int {
|
||||
val, ok := getPluginSetting(mmConfig, key)
|
||||
if !ok {
|
||||
return def
|
||||
}
|
||||
valFloat, ok := val.(float64)
|
||||
if !ok {
|
||||
return def
|
||||
}
|
||||
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
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package boards
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
@ -29,15 +29,15 @@ func (c *configuration) Clone() *configuration {
|
||||
// getConfiguration retrieves the active configuration under lock, making it safe to use
|
||||
// concurrently. The active configuration may change underneath the client of this method, but
|
||||
// the struct returned by this API call is considered immutable.
|
||||
func (p *Plugin) getConfiguration() *configuration {
|
||||
p.configurationLock.RLock()
|
||||
defer p.configurationLock.RUnlock()
|
||||
func (b *BoardsApp) getConfiguration() *configuration {
|
||||
b.configurationLock.RLock()
|
||||
defer b.configurationLock.RUnlock()
|
||||
|
||||
if p.configuration == nil {
|
||||
if b.configuration == nil {
|
||||
return &configuration{}
|
||||
}
|
||||
|
||||
return p.configuration
|
||||
return b.configuration
|
||||
}
|
||||
|
||||
// setConfiguration replaces the active configuration under lock.
|
||||
@ -49,11 +49,11 @@ func (p *Plugin) getConfiguration() *configuration {
|
||||
// This method panics if setConfiguration is called with the existing configuration. This almost
|
||||
// certainly means that the configuration was modified without being cloned and may result in
|
||||
// an unsafe access.
|
||||
func (p *Plugin) setConfiguration(configuration *configuration) {
|
||||
p.configurationLock.Lock()
|
||||
defer p.configurationLock.Unlock()
|
||||
func (b *BoardsApp) setConfiguration(configuration *configuration) {
|
||||
b.configurationLock.Lock()
|
||||
defer b.configurationLock.Unlock()
|
||||
|
||||
if configuration != nil && p.configuration == configuration {
|
||||
if configuration != nil && b.configuration == configuration {
|
||||
// Ignore assignment if the configuration struct is empty. Go will optimize the
|
||||
// allocation for same to point at the same memory address, breaking the check
|
||||
// above.
|
||||
@ -64,41 +64,41 @@ func (p *Plugin) setConfiguration(configuration *configuration) {
|
||||
panic("setConfiguration called with the existing configuration")
|
||||
}
|
||||
|
||||
p.configuration = configuration
|
||||
b.configuration = configuration
|
||||
}
|
||||
|
||||
// OnConfigurationChange is invoked when configuration changes may have been made.
|
||||
func (p *Plugin) OnConfigurationChange() error {
|
||||
func (b *BoardsApp) OnConfigurationChange() error {
|
||||
// Have we been setup by OnActivate?
|
||||
if p.wsPluginAdapter == nil {
|
||||
if b.server == nil {
|
||||
return nil
|
||||
}
|
||||
mmconfig := p.API.GetConfig()
|
||||
mmconfig := b.servicesAPI.GetConfig()
|
||||
|
||||
// handle plugin configuration settings
|
||||
enableShareBoards := false
|
||||
if mmconfig.PluginSettings.Plugins[pluginName][sharedBoardsName] == true {
|
||||
if mmconfig.PluginSettings.Plugins[PluginName][SharedBoardsName] == true {
|
||||
enableShareBoards = true
|
||||
}
|
||||
configuration := &configuration{
|
||||
EnablePublicSharedBoards: enableShareBoards,
|
||||
}
|
||||
p.setConfiguration(configuration)
|
||||
p.server.Config().EnablePublicSharedBoards = enableShareBoards
|
||||
b.setConfiguration(configuration)
|
||||
b.server.Config().EnablePublicSharedBoards = enableShareBoards
|
||||
|
||||
// handle feature flags
|
||||
p.server.Config().FeatureFlags = parseFeatureFlags(mmconfig.FeatureFlags.ToMap())
|
||||
b.server.Config().FeatureFlags = parseFeatureFlags(mmconfig.FeatureFlags.ToMap())
|
||||
|
||||
// handle Data Retention settings
|
||||
enableBoardsDeletion := false
|
||||
if mmconfig.DataRetentionSettings.EnableBoardsDeletion != nil {
|
||||
enableBoardsDeletion = true
|
||||
}
|
||||
p.server.Config().EnableDataRetention = enableBoardsDeletion
|
||||
p.server.Config().DataRetentionDays = *mmconfig.DataRetentionSettings.BoardsRetentionDays
|
||||
p.server.Config().TeammateNameDisplay = *mmconfig.TeamSettings.TeammateNameDisplay
|
||||
b.server.Config().EnableDataRetention = enableBoardsDeletion
|
||||
b.server.Config().DataRetentionDays = *mmconfig.DataRetentionSettings.BoardsRetentionDays
|
||||
b.server.Config().TeammateNameDisplay = *mmconfig.TeamSettings.TeammateNameDisplay
|
||||
|
||||
p.server.UpdateAppConfig()
|
||||
p.wsPluginAdapter.BroadcastConfigChange(*p.server.App().GetClientConfig())
|
||||
b.server.UpdateAppConfig()
|
||||
b.wsPluginAdapter.BroadcastConfigChange(*b.server.App().GetClientConfig())
|
||||
return nil
|
||||
}
|
@ -1,18 +1,21 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package main
|
||||
package boards
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/mattermost/focalboard/server/integrationtests"
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
"github.com/mattermost/focalboard/server/server"
|
||||
"github.com/mattermost/focalboard/server/ws"
|
||||
|
||||
mockservicesapi "github.com/mattermost/focalboard/server/model/mocks"
|
||||
|
||||
serverModel "github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/plugin/plugintest"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -40,16 +43,16 @@ func newTestServer() *server.Server {
|
||||
return integrationtests.NewTestServerPluginMode()
|
||||
}
|
||||
func TestConfigurationNullConfiguration(t *testing.T) {
|
||||
plugin := &Plugin{}
|
||||
assert.NotNil(t, plugin.getConfiguration())
|
||||
boardsApp := &BoardsApp{}
|
||||
assert.NotNil(t, boardsApp.getConfiguration())
|
||||
}
|
||||
|
||||
func TestOnConfigurationChange(t *testing.T) {
|
||||
stringRef := ""
|
||||
|
||||
basePlugins := make(map[string]map[string]interface{})
|
||||
basePlugins[pluginName] = make(map[string]interface{})
|
||||
basePlugins[pluginName][sharedBoardsName] = true
|
||||
basePlugins[PluginName] = make(map[string]interface{})
|
||||
basePlugins[PluginName][SharedBoardsName] = true
|
||||
|
||||
baseFeatureFlags := &serverModel.FeatureFlags{
|
||||
BoardsFeatureFlags: "Feature1-Feature2",
|
||||
@ -77,26 +80,29 @@ func TestOnConfigurationChange(t *testing.T) {
|
||||
t.Run("Test Load Plugin Success", func(t *testing.T) {
|
||||
th, tearDown := SetupTestHelper(t)
|
||||
defer tearDown()
|
||||
api := &plugintest.API{}
|
||||
api.On("GetUnsanitizedConfig").Return(baseConfig)
|
||||
api.On("GetConfig").Return(baseConfig)
|
||||
|
||||
p := Plugin{}
|
||||
p.SetAPI(api)
|
||||
p.server = th.Server
|
||||
p.wsPluginAdapter = &FakePluginAdapter{}
|
||||
ctrl := gomock.NewController(t)
|
||||
api := mockservicesapi.NewMockServicesAPI(ctrl)
|
||||
api.EXPECT().GetConfig().Return(baseConfig)
|
||||
|
||||
err := p.OnConfigurationChange()
|
||||
b := &BoardsApp{
|
||||
server: th.Server,
|
||||
wsPluginAdapter: &FakePluginAdapter{},
|
||||
servicesAPI: api,
|
||||
logger: mlog.CreateConsoleTestLogger(true, mlog.LvlError),
|
||||
}
|
||||
|
||||
err := b.OnConfigurationChange()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, count)
|
||||
|
||||
// make sure both App and Server got updated
|
||||
assert.True(t, p.server.Config().EnablePublicSharedBoards)
|
||||
assert.True(t, p.server.App().GetClientConfig().EnablePublicSharedBoards)
|
||||
assert.True(t, b.server.Config().EnablePublicSharedBoards)
|
||||
assert.True(t, b.server.App().GetClientConfig().EnablePublicSharedBoards)
|
||||
|
||||
assert.Equal(t, "true", p.server.Config().FeatureFlags["Feature1"])
|
||||
assert.Equal(t, "true", p.server.Config().FeatureFlags["Feature2"])
|
||||
assert.Equal(t, "", p.server.Config().FeatureFlags["Feature3"])
|
||||
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"])
|
||||
})
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
package main
|
||||
package boards
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -9,17 +9,17 @@ import (
|
||||
|
||||
var ErrInsufficientLicense = errors.New("appropriate license required")
|
||||
|
||||
func (p *Plugin) RunDataRetention(nowTime, batchSize int64) (int64, error) {
|
||||
p.server.Logger().Debug("Boards RunDataRetention")
|
||||
license := p.server.Store().GetLicense()
|
||||
func (b *BoardsApp) RunDataRetention(nowTime, batchSize int64) (int64, error) {
|
||||
b.logger.Debug("Boards RunDataRetention")
|
||||
license := b.server.Store().GetLicense()
|
||||
if license == nil || !(*license.Features.DataRetention) {
|
||||
return 0, ErrInsufficientLicense
|
||||
}
|
||||
|
||||
if p.server.Config().EnableDataRetention {
|
||||
boardsRetentionDays := p.server.Config().DataRetentionDays
|
||||
if b.server.Config().EnableDataRetention {
|
||||
boardsRetentionDays := b.server.Config().DataRetentionDays
|
||||
endTimeBoards := convertDaysToCutoff(boardsRetentionDays, time.Unix(nowTime/1000, 0))
|
||||
return p.server.Store().RunDataRetention(endTimeBoards, batchSize)
|
||||
return b.server.Store().RunDataRetention(endTimeBoards, batchSize)
|
||||
}
|
||||
return 0, nil
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package main
|
||||
package boards
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -12,9 +13,10 @@ import (
|
||||
"github.com/mattermost/focalboard/server/services/config"
|
||||
"github.com/mattermost/focalboard/server/services/permissions/localpermissions"
|
||||
"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/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type TestHelperMockStore struct {
|
||||
@ -22,17 +24,24 @@ type TestHelperMockStore struct {
|
||||
Store *mockstore.MockStore
|
||||
}
|
||||
|
||||
func SetupTestHelperMockStore(t *testing.T) *TestHelperMockStore {
|
||||
func SetupTestHelperMockStore(t *testing.T) (*TestHelperMockStore, func()) {
|
||||
th := &TestHelperMockStore{}
|
||||
|
||||
origUnitTesting := os.Getenv("FOCALBOARD_UNIT_TESTING")
|
||||
os.Setenv("FOCALBOARD_UNIT_TESTING", "1")
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
mockStore := mockstore.NewMockStore(ctrl)
|
||||
|
||||
tearDown := func() {
|
||||
defer ctrl.Finish()
|
||||
os.Setenv("FOCALBOARD_UNIT_TESTING", origUnitTesting)
|
||||
}
|
||||
|
||||
th.Server = newTestServerMock(mockStore)
|
||||
th.Store = mockStore
|
||||
|
||||
return th
|
||||
return th, tearDown
|
||||
}
|
||||
|
||||
func newTestServerMock(mockStore *mockstore.MockStore) *server.Server {
|
||||
@ -67,15 +76,19 @@ func newTestServerMock(mockStore *mockstore.MockStore) *server.Server {
|
||||
}
|
||||
|
||||
func TestRunDataRetention(t *testing.T) {
|
||||
th := SetupTestHelperMockStore(t)
|
||||
plugin := Plugin{}
|
||||
plugin.server = th.Server
|
||||
th, tearDown := SetupTestHelperMockStore(t)
|
||||
defer tearDown()
|
||||
|
||||
b := &BoardsApp{
|
||||
server: th.Server,
|
||||
logger: mlog.CreateConsoleTestLogger(true, mlog.LvlError),
|
||||
}
|
||||
|
||||
now := time.Now().UnixNano()
|
||||
|
||||
t.Run("test null license", func(t *testing.T) {
|
||||
th.Store.EXPECT().GetLicense().Return(nil)
|
||||
_, err := plugin.RunDataRetention(now, 10)
|
||||
_, err := b.RunDataRetention(now, 10)
|
||||
assert.NotNil(t, err)
|
||||
assert.Equal(t, ErrInsufficientLicense, err)
|
||||
})
|
||||
@ -90,7 +103,7 @@ func TestRunDataRetention(t *testing.T) {
|
||||
},
|
||||
},
|
||||
)
|
||||
_, err := plugin.RunDataRetention(now, 10)
|
||||
_, err := b.RunDataRetention(now, 10)
|
||||
assert.NotNil(t, err)
|
||||
assert.Equal(t, ErrInsufficientLicense, err)
|
||||
})
|
||||
@ -104,7 +117,7 @@ func TestRunDataRetention(t *testing.T) {
|
||||
},
|
||||
})
|
||||
|
||||
count, err := plugin.RunDataRetention(now, 10)
|
||||
count, err := b.RunDataRetention(now, 10)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, int64(0), count)
|
||||
})
|
||||
@ -119,9 +132,9 @@ func TestRunDataRetention(t *testing.T) {
|
||||
})
|
||||
|
||||
th.Store.EXPECT().RunDataRetention(gomock.Any(), int64(10)).Return(int64(100), nil)
|
||||
plugin.server.Config().EnableDataRetention = true
|
||||
b.server.Config().EnableDataRetention = true
|
||||
|
||||
count, err := plugin.RunDataRetention(now, 10)
|
||||
count, err := b.RunDataRetention(now, 10)
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, int64(100), count)
|
34
mattermost-plugin/server/boards/mutex_adapter.go
Normal file
34
mattermost-plugin/server/boards/mutex_adapter.go
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package boards
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
mm_model "github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
)
|
||||
|
||||
type mutexAPIAdapter struct {
|
||||
api model.ServicesAPI
|
||||
}
|
||||
|
||||
func (m *mutexAPIAdapter) KVSetWithOptions(key string, value []byte, options mm_model.PluginKVSetOptions) (bool, *mm_model.AppError) {
|
||||
b, err := m.api.KVSetWithOptions(key, value, options)
|
||||
|
||||
var appErr *mm_model.AppError
|
||||
if err != nil {
|
||||
if !errors.As(err, &appErr) {
|
||||
appErr = mm_model.NewAppError("KVSetWithOptions", "", nil, "", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
return b, appErr
|
||||
}
|
||||
|
||||
func (m *mutexAPIAdapter) LogError(msg string, keyValuePairs ...interface{}) {
|
||||
m.api.GetLogger().Error(msg, mlog.Array("kvpairs", keyValuePairs))
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package boards
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -12,8 +12,6 @@ import (
|
||||
"github.com/mattermost/focalboard/server/services/permissions"
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
|
||||
pluginapi "github.com/mattermost/mattermost-plugin-api"
|
||||
|
||||
mm_model "github.com/mattermost/mattermost-server/v6/model"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
@ -27,15 +25,15 @@ const (
|
||||
|
||||
type notifyBackendParams struct {
|
||||
cfg *config.Configuration
|
||||
client *pluginapi.Client
|
||||
servicesAPI model.ServicesAPI
|
||||
permissions permissions.PermissionsService
|
||||
appAPI *appAPI
|
||||
serverRoot string
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
}
|
||||
|
||||
func createMentionsNotifyBackend(params notifyBackendParams) (*notifymentions.Backend, error) {
|
||||
delivery, err := createDelivery(params.client, params.serverRoot)
|
||||
delivery, err := createDelivery(params.servicesAPI, params.serverRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -53,7 +51,7 @@ func createMentionsNotifyBackend(params notifyBackendParams) (*notifymentions.Ba
|
||||
}
|
||||
|
||||
func createSubscriptionsNotifyBackend(params notifyBackendParams) (*notifysubscriptions.Backend, error) {
|
||||
delivery, err := createDelivery(params.client, params.serverRoot)
|
||||
delivery, err := createDelivery(params.servicesAPI, params.serverRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -72,58 +70,18 @@ func createSubscriptionsNotifyBackend(params notifyBackendParams) (*notifysubscr
|
||||
return backend, nil
|
||||
}
|
||||
|
||||
func createDelivery(client *pluginapi.Client, serverRoot string) (*plugindelivery.PluginDelivery, error) {
|
||||
func createDelivery(servicesAPI model.ServicesAPI, serverRoot string) (*plugindelivery.PluginDelivery, error) {
|
||||
bot := &mm_model.Bot{
|
||||
Username: botUsername,
|
||||
DisplayName: botDisplayname,
|
||||
Description: botDescription,
|
||||
}
|
||||
botID, err := client.Bot.EnsureBot(bot)
|
||||
botID, err := servicesAPI.EnsureBot(bot)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to ensure %s bot: %w", botDisplayname, err)
|
||||
}
|
||||
|
||||
pluginAPI := &pluginAPIAdapter{client: client}
|
||||
|
||||
return plugindelivery.New(botID, serverRoot, pluginAPI), nil
|
||||
}
|
||||
|
||||
// pluginAPIAdapter provides a simple wrapper around the component based Plugin API
|
||||
// which flattens the API to satisfy an interface.
|
||||
type pluginAPIAdapter struct {
|
||||
client *pluginapi.Client
|
||||
}
|
||||
|
||||
func (da *pluginAPIAdapter) GetDirectChannel(userID1, userID2 string) (*mm_model.Channel, error) {
|
||||
return da.client.Channel.GetDirect(userID1, userID2)
|
||||
}
|
||||
|
||||
func (da *pluginAPIAdapter) CreatePost(post *mm_model.Post) error {
|
||||
return da.client.Post.CreatePost(post)
|
||||
}
|
||||
|
||||
func (da *pluginAPIAdapter) GetUserByID(userID string) (*mm_model.User, error) {
|
||||
return da.client.User.Get(userID)
|
||||
}
|
||||
|
||||
func (da *pluginAPIAdapter) GetUserByUsername(name string) (*mm_model.User, error) {
|
||||
return da.client.User.GetByUsername(name)
|
||||
}
|
||||
|
||||
func (da *pluginAPIAdapter) GetTeamMember(teamID string, userID string) (*mm_model.TeamMember, error) {
|
||||
return da.client.Team.GetMember(teamID, userID)
|
||||
}
|
||||
|
||||
func (da *pluginAPIAdapter) GetChannelByID(channelID string) (*mm_model.Channel, error) {
|
||||
return da.client.Channel.Get(channelID)
|
||||
}
|
||||
|
||||
func (da *pluginAPIAdapter) GetChannelMember(channelID string, userID string) (*mm_model.ChannelMember, error) {
|
||||
return da.client.Channel.GetMember(channelID, userID)
|
||||
}
|
||||
|
||||
func (da *pluginAPIAdapter) CreateMember(teamID string, userID string) (*mm_model.TeamMember, error) {
|
||||
return da.client.Team.CreateMember(teamID, userID)
|
||||
return plugindelivery.New(botID, serverRoot, servicesAPI), nil
|
||||
}
|
||||
|
||||
type appIface interface {
|
163
mattermost-plugin/server/boards/post.go
Normal file
163
mattermost-plugin/server/boards/post.go
Normal file
@ -0,0 +1,163 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package boards
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
mm_model "github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/markdown"
|
||||
)
|
||||
|
||||
func postWithBoardsEmbed(post *mm_model.Post) *mm_model.Post {
|
||||
if _, ok := post.GetProps()["boards"]; ok {
|
||||
post.AddProp("boards", nil)
|
||||
}
|
||||
|
||||
firstLink, newPostMessage := getFirstLinkAndShortenAllBoardsLink(post.Message)
|
||||
post.Message = newPostMessage
|
||||
|
||||
if firstLink == "" {
|
||||
return post
|
||||
}
|
||||
|
||||
u, err := url.Parse(firstLink)
|
||||
|
||||
if err != nil {
|
||||
return post
|
||||
}
|
||||
|
||||
// Trim away the first / because otherwise after we split the string, the first element in the array is a empty element
|
||||
urlPath := u.Path
|
||||
urlPath = strings.TrimPrefix(urlPath, "/")
|
||||
urlPath = strings.TrimSuffix(urlPath, "/")
|
||||
pathSplit := strings.Split(strings.ToLower(urlPath), "/")
|
||||
queryParams := u.Query()
|
||||
|
||||
if len(pathSplit) == 0 {
|
||||
return post
|
||||
}
|
||||
|
||||
teamID, boardID, viewID, cardID := returnBoardsParams(pathSplit)
|
||||
|
||||
if teamID != "" && boardID != "" && viewID != "" && cardID != "" {
|
||||
b, _ := json.Marshal(BoardsEmbed{
|
||||
TeamID: teamID,
|
||||
BoardID: boardID,
|
||||
ViewID: viewID,
|
||||
CardID: cardID,
|
||||
ReadToken: queryParams.Get("r"),
|
||||
OriginalPath: u.RequestURI(),
|
||||
})
|
||||
|
||||
BoardsPostEmbed := &mm_model.PostEmbed{
|
||||
Type: mm_model.PostEmbedBoards,
|
||||
Data: string(b),
|
||||
}
|
||||
|
||||
if post.Metadata == nil {
|
||||
post.Metadata = &mm_model.PostMetadata{}
|
||||
}
|
||||
|
||||
post.Metadata.Embeds = []*mm_model.PostEmbed{BoardsPostEmbed}
|
||||
post.AddProp("boards", string(b))
|
||||
}
|
||||
|
||||
return post
|
||||
}
|
||||
|
||||
func getFirstLinkAndShortenAllBoardsLink(postMessage string) (firstLink, newPostMessage string) {
|
||||
newPostMessage = postMessage
|
||||
seenLinks := make(map[string]bool)
|
||||
markdown.Inspect(postMessage, func(blockOrInline interface{}) bool {
|
||||
if autoLink, ok := blockOrInline.(*markdown.Autolink); ok {
|
||||
link := autoLink.Destination()
|
||||
|
||||
if firstLink == "" {
|
||||
firstLink = link
|
||||
}
|
||||
|
||||
if seen := seenLinks[link]; !seen && isBoardsLink(link) {
|
||||
// TODO: Make sure that <Jump To Card> is Internationalized and translated to the Users Language preference
|
||||
markdownFormattedLink := fmt.Sprintf("[%s](%s)", "<Jump To Card>", link)
|
||||
newPostMessage = strings.ReplaceAll(newPostMessage, link, markdownFormattedLink)
|
||||
seenLinks[link] = true
|
||||
}
|
||||
}
|
||||
if inlineLink, ok := blockOrInline.(*markdown.InlineLink); ok {
|
||||
if link := inlineLink.Destination(); firstLink == "" {
|
||||
firstLink = link
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
return firstLink, newPostMessage
|
||||
}
|
||||
|
||||
func returnBoardsParams(pathArray []string) (teamID, boardID, viewID, cardID string) {
|
||||
// The reason we are doing this search for the first instance of boards or plugins is to take into account URL subpaths
|
||||
index := -1
|
||||
for i := 0; i < len(pathArray); i++ {
|
||||
if pathArray[i] == "boards" || pathArray[i] == "plugins" {
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if index == -1 {
|
||||
return teamID, boardID, viewID, cardID
|
||||
}
|
||||
|
||||
// If at index, the parameter in the path is boards,
|
||||
// then we've copied this directly as logged in user of that board
|
||||
|
||||
// If at index, the parameter in the path is plugins,
|
||||
// then we've copied this from a shared board
|
||||
|
||||
// For card links copied on a non-shared board, the path looks like {...Mattermost Url}.../boards/team/teamID/boardID/viewID/cardID
|
||||
|
||||
// For card links copied on a shared board, the path looks like
|
||||
// {...Mattermost Url}.../plugins/focalboard/team/teamID/shared/boardID/viewID/cardID?r=read_token
|
||||
|
||||
// This is a non-shared board card link
|
||||
if len(pathArray)-index == 6 && pathArray[index] == "boards" && pathArray[index+1] == "team" {
|
||||
teamID = pathArray[index+2]
|
||||
boardID = pathArray[index+3]
|
||||
viewID = pathArray[index+4]
|
||||
cardID = pathArray[index+5]
|
||||
} else if len(pathArray)-index == 8 && pathArray[index] == "plugins" &&
|
||||
pathArray[index+1] == "focalboard" &&
|
||||
pathArray[index+2] == "team" &&
|
||||
pathArray[index+4] == "shared" { // This is a shared board card link
|
||||
teamID = pathArray[index+3]
|
||||
boardID = pathArray[index+5]
|
||||
viewID = pathArray[index+6]
|
||||
cardID = pathArray[index+7]
|
||||
}
|
||||
return teamID, boardID, viewID, cardID
|
||||
}
|
||||
|
||||
func isBoardsLink(link string) bool {
|
||||
u, err := url.Parse(link)
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
urlPath := u.Path
|
||||
urlPath = strings.TrimPrefix(urlPath, "/")
|
||||
urlPath = strings.TrimSuffix(urlPath, "/")
|
||||
pathSplit := strings.Split(strings.ToLower(urlPath), "/")
|
||||
|
||||
if len(pathSplit) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
teamID, boardID, viewID, cardID := returnBoardsParams(pathSplit)
|
||||
return teamID != "" && boardID != "" && viewID != "" && cardID != ""
|
||||
}
|
@ -1,76 +1,38 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/mattermost/focalboard/server/auth"
|
||||
"github.com/mattermost/focalboard/server/server"
|
||||
"github.com/mattermost/focalboard/server/services/config"
|
||||
"github.com/mattermost/focalboard/server/services/notify"
|
||||
"github.com/mattermost/focalboard/server/services/permissions/mmpermissions"
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
"github.com/mattermost/focalboard/server/services/store/mattermostauthlayer"
|
||||
"github.com/mattermost/focalboard/server/services/store/sqlstore"
|
||||
"github.com/mattermost/focalboard/server/utils"
|
||||
"github.com/mattermost/focalboard/server/ws"
|
||||
"github.com/mattermost/focalboard/mattermost-plugin/server/boards"
|
||||
|
||||
pluginapi "github.com/mattermost/mattermost-plugin-api"
|
||||
"github.com/mattermost/mattermost-plugin-api/cluster"
|
||||
|
||||
mmModel "github.com/mattermost/mattermost-server/v6/model"
|
||||
mm_model "github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/plugin"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/markdown"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
const (
|
||||
boardsFeatureFlagName = "BoardsFeatureFlags"
|
||||
pluginName = "focalboard"
|
||||
sharedBoardsName = "enablepublicsharedboards"
|
||||
|
||||
notifyFreqCardSecondsKey = "notify_freq_card_seconds"
|
||||
notifyFreqBoardSecondsKey = "notify_freq_board_seconds"
|
||||
)
|
||||
|
||||
type BoardsEmbed struct {
|
||||
OriginalPath string `json:"originalPath"`
|
||||
TeamID string `json:"teamID"`
|
||||
ViewID string `json:"viewID"`
|
||||
BoardID string `json:"boardID"`
|
||||
CardID string `json:"cardID"`
|
||||
ReadToken string `json:"readToken,omitempty"`
|
||||
}
|
||||
var ErrPluginNotAllowed = errors.New("boards plugin not allowed while Boards product enabled")
|
||||
|
||||
// Plugin implements the interface expected by the Mattermost server to communicate between the server and plugin processes.
|
||||
type Plugin struct {
|
||||
plugin.MattermostPlugin
|
||||
|
||||
// configurationLock synchronizes access to the configuration.
|
||||
configurationLock sync.RWMutex
|
||||
|
||||
// configuration is the active plugin configuration. Consult getConfiguration and
|
||||
// setConfiguration for usage.
|
||||
configuration *configuration
|
||||
|
||||
server *server.Server
|
||||
wsPluginAdapter ws.PluginAdapterInterface
|
||||
boardsApp *boards.BoardsApp
|
||||
}
|
||||
|
||||
func (p *Plugin) OnActivate() error {
|
||||
mmconfig := p.API.GetUnsanitizedConfig()
|
||||
if p.API.GetConfig().FeatureFlags.BoardsProduct {
|
||||
p.API.LogError(ErrPluginNotAllowed.Error())
|
||||
return ErrPluginNotAllowed
|
||||
}
|
||||
|
||||
client := pluginapi.NewClient(p.API, p.Driver)
|
||||
sqlDB, err := client.Store.GetMasterDB()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error initializing the DB: %w", err)
|
||||
}
|
||||
|
||||
logger, _ := mlog.NewLogger()
|
||||
pluginTargetFactory := newPluginTargetFactory(&client.Log)
|
||||
@ -78,257 +40,71 @@ func (p *Plugin) OnActivate() error {
|
||||
TargetFactory: pluginTargetFactory.createTarget,
|
||||
}
|
||||
cfgJSON := defaultLoggingConfig()
|
||||
err = logger.Configure("", cfgJSON, factories)
|
||||
err := logger.Configure("", cfgJSON, factories)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
baseURL := ""
|
||||
if mmconfig.ServiceSettings.SiteURL != nil {
|
||||
baseURL = *mmconfig.ServiceSettings.SiteURL
|
||||
}
|
||||
serverID := client.System.GetDiagnosticID()
|
||||
cfg := p.createBoardsConfig(*mmconfig, baseURL, serverID)
|
||||
adapter := newServiceAPIAdapter(p.API, client.Store, logger)
|
||||
|
||||
storeParams := sqlstore.Params{
|
||||
DBType: cfg.DBType,
|
||||
ConnectionString: cfg.DBConfigString,
|
||||
TablePrefix: cfg.DBTablePrefix,
|
||||
Logger: logger,
|
||||
DB: sqlDB,
|
||||
IsPlugin: true,
|
||||
NewMutexFn: func(name string) (*cluster.Mutex, error) {
|
||||
return cluster.NewMutex(p.API, name)
|
||||
},
|
||||
PluginAPI: &p.API,
|
||||
}
|
||||
|
||||
var db store.Store
|
||||
db, err = sqlstore.New(storeParams)
|
||||
boardsApp, err := boards.NewBoardsApp(adapter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error initializing the DB: %w", err)
|
||||
}
|
||||
if cfg.AuthMode == server.MattermostAuthMod {
|
||||
layeredStore, err2 := mattermostauthlayer.New(cfg.DBType, sqlDB, db, logger, p.API, storeParams.TablePrefix, client)
|
||||
if err2 != nil {
|
||||
return fmt.Errorf("error initializing the DB: %w", err2)
|
||||
}
|
||||
db = layeredStore
|
||||
return fmt.Errorf("cannot activate plugin: %w", err)
|
||||
}
|
||||
|
||||
permissionsService := mmpermissions.New(db, p.API)
|
||||
|
||||
p.wsPluginAdapter = ws.NewPluginAdapter(p.API, auth.New(cfg, db, permissionsService), db, logger)
|
||||
|
||||
backendParams := notifyBackendParams{
|
||||
cfg: cfg,
|
||||
client: client,
|
||||
appAPI: &appAPI{store: db},
|
||||
permissions: permissionsService,
|
||||
serverRoot: baseURL + "/boards",
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
var notifyBackends []notify.Backend
|
||||
|
||||
mentionsBackend, err := createMentionsNotifyBackend(backendParams)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating mention notifications backend: %w", err)
|
||||
}
|
||||
notifyBackends = append(notifyBackends, mentionsBackend)
|
||||
|
||||
subscriptionsBackend, err2 := createSubscriptionsNotifyBackend(backendParams)
|
||||
if err2 != nil {
|
||||
return fmt.Errorf("error creating subscription notifications backend: %w", err2)
|
||||
}
|
||||
notifyBackends = append(notifyBackends, subscriptionsBackend)
|
||||
mentionsBackend.AddListener(subscriptionsBackend)
|
||||
|
||||
params := server.Params{
|
||||
Cfg: cfg,
|
||||
SingleUserToken: "",
|
||||
DBStore: db,
|
||||
Logger: logger,
|
||||
ServerID: serverID,
|
||||
WSAdapter: p.wsPluginAdapter,
|
||||
NotifyBackends: notifyBackends,
|
||||
PermissionsService: permissionsService,
|
||||
PluginAPI: p.API,
|
||||
Client: client,
|
||||
IsPlugin: true,
|
||||
}
|
||||
|
||||
server, err := server.New(params)
|
||||
if err != nil {
|
||||
fmt.Println("ERROR INITIALIZING THE SERVER", err)
|
||||
return err
|
||||
}
|
||||
|
||||
backendParams.appAPI.init(db, server.App())
|
||||
|
||||
if utils.IsCloudLicense(p.API.GetLicense()) {
|
||||
limits, err := p.API.GetCloudLimits()
|
||||
if err != nil {
|
||||
fmt.Println("ERROR FETCHING CLOUD LIMITS WHEN STARTING THE PLUGIN", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := server.App().SetCloudLimits(limits); err != nil {
|
||||
fmt.Println("ERROR SETTING CLOUD LIMITS WHEN STARTING THE PLUGIN", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
p.server = server
|
||||
return server.Start()
|
||||
p.boardsApp = boardsApp
|
||||
return p.boardsApp.Start()
|
||||
}
|
||||
|
||||
func (p *Plugin) createBoardsConfig(mmconfig mmModel.Config, baseURL string, serverID string) *config.Configuration {
|
||||
filesS3Config := config.AmazonS3Config{}
|
||||
if mmconfig.FileSettings.AmazonS3AccessKeyId != nil {
|
||||
filesS3Config.AccessKeyID = *mmconfig.FileSettings.AmazonS3AccessKeyId
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3SecretAccessKey != nil {
|
||||
filesS3Config.SecretAccessKey = *mmconfig.FileSettings.AmazonS3SecretAccessKey
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3Bucket != nil {
|
||||
filesS3Config.Bucket = *mmconfig.FileSettings.AmazonS3Bucket
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3PathPrefix != nil {
|
||||
filesS3Config.PathPrefix = *mmconfig.FileSettings.AmazonS3PathPrefix
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3Region != nil {
|
||||
filesS3Config.Region = *mmconfig.FileSettings.AmazonS3Region
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3Endpoint != nil {
|
||||
filesS3Config.Endpoint = *mmconfig.FileSettings.AmazonS3Endpoint
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3SSL != nil {
|
||||
filesS3Config.SSL = *mmconfig.FileSettings.AmazonS3SSL
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3SignV2 != nil {
|
||||
filesS3Config.SignV2 = *mmconfig.FileSettings.AmazonS3SignV2
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3SSE != nil {
|
||||
filesS3Config.SSE = *mmconfig.FileSettings.AmazonS3SSE
|
||||
}
|
||||
if mmconfig.FileSettings.AmazonS3Trace != nil {
|
||||
filesS3Config.Trace = *mmconfig.FileSettings.AmazonS3Trace
|
||||
// OnConfigurationChange is invoked when configuration changes may have been made.
|
||||
func (p *Plugin) OnConfigurationChange() error {
|
||||
// Have we been setup by OnActivate?
|
||||
if p.boardsApp == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
enableTelemetry := false
|
||||
if mmconfig.LogSettings.EnableDiagnostics != nil {
|
||||
enableTelemetry = *mmconfig.LogSettings.EnableDiagnostics
|
||||
}
|
||||
|
||||
enablePublicSharedBoards := false
|
||||
if mmconfig.PluginSettings.Plugins[pluginName][sharedBoardsName] == true {
|
||||
enablePublicSharedBoards = true
|
||||
}
|
||||
|
||||
enableBoardsDeletion := false
|
||||
if mmconfig.DataRetentionSettings.EnableBoardsDeletion != nil {
|
||||
enableBoardsDeletion = true
|
||||
}
|
||||
|
||||
featureFlags := parseFeatureFlags(mmconfig.FeatureFlags.ToMap())
|
||||
|
||||
return &config.Configuration{
|
||||
ServerRoot: baseURL + "/plugins/focalboard",
|
||||
Port: -1,
|
||||
DBType: *mmconfig.SqlSettings.DriverName,
|
||||
DBConfigString: *mmconfig.SqlSettings.DataSource,
|
||||
DBTablePrefix: "focalboard_",
|
||||
UseSSL: false,
|
||||
SecureCookie: true,
|
||||
WebPath: path.Join(*mmconfig.PluginSettings.Directory, "focalboard", "pack"),
|
||||
FilesDriver: *mmconfig.FileSettings.DriverName,
|
||||
FilesPath: *mmconfig.FileSettings.Directory,
|
||||
FilesS3Config: filesS3Config,
|
||||
MaxFileSize: *mmconfig.FileSettings.MaxFileSize,
|
||||
Telemetry: enableTelemetry,
|
||||
TelemetryID: serverID,
|
||||
WebhookUpdate: []string{},
|
||||
SessionExpireTime: 2592000,
|
||||
SessionRefreshTime: 18000,
|
||||
LocalOnly: false,
|
||||
EnableLocalMode: false,
|
||||
LocalModeSocketLocation: "",
|
||||
AuthMode: "mattermost",
|
||||
EnablePublicSharedBoards: enablePublicSharedBoards,
|
||||
FeatureFlags: featureFlags,
|
||||
NotifyFreqCardSeconds: getPluginSettingInt(mmconfig, notifyFreqCardSecondsKey, 120),
|
||||
NotifyFreqBoardSeconds: getPluginSettingInt(mmconfig, notifyFreqBoardSecondsKey, 86400),
|
||||
EnableDataRetention: enableBoardsDeletion,
|
||||
DataRetentionDays: *mmconfig.DataRetentionSettings.BoardsRetentionDays,
|
||||
TeammateNameDisplay: *mmconfig.TeamSettings.TeammateNameDisplay,
|
||||
}
|
||||
}
|
||||
|
||||
func getPluginSetting(mmConfig mmModel.Config, key string) (interface{}, bool) {
|
||||
plugin, ok := mmConfig.PluginSettings.Plugins[pluginName]
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
val, ok := plugin[key]
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
return val, true
|
||||
}
|
||||
|
||||
func getPluginSettingInt(mmConfig mmModel.Config, key string, def int) int {
|
||||
val, ok := getPluginSetting(mmConfig, key)
|
||||
if !ok {
|
||||
return def
|
||||
}
|
||||
valFloat, ok := val.(float64)
|
||||
if !ok {
|
||||
return def
|
||||
}
|
||||
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
|
||||
return p.boardsApp.OnConfigurationChange()
|
||||
}
|
||||
|
||||
func (p *Plugin) OnWebSocketConnect(webConnID, userID string) {
|
||||
p.wsPluginAdapter.OnWebSocketConnect(webConnID, userID)
|
||||
p.boardsApp.OnWebSocketConnect(webConnID, userID)
|
||||
}
|
||||
|
||||
func (p *Plugin) OnWebSocketDisconnect(webConnID, userID string) {
|
||||
p.wsPluginAdapter.OnWebSocketDisconnect(webConnID, userID)
|
||||
p.boardsApp.OnWebSocketDisconnect(webConnID, userID)
|
||||
}
|
||||
|
||||
func (p *Plugin) WebSocketMessageHasBeenPosted(webConnID, userID string, req *mmModel.WebSocketRequest) {
|
||||
p.wsPluginAdapter.WebSocketMessageHasBeenPosted(webConnID, userID, req)
|
||||
func (p *Plugin) WebSocketMessageHasBeenPosted(webConnID, userID string, req *mm_model.WebSocketRequest) {
|
||||
p.boardsApp.WebSocketMessageHasBeenPosted(webConnID, userID, req)
|
||||
}
|
||||
|
||||
func (p *Plugin) OnDeactivate() error {
|
||||
return p.server.Shutdown()
|
||||
return p.boardsApp.Stop()
|
||||
}
|
||||
|
||||
func (p *Plugin) OnPluginClusterEvent(_ *plugin.Context, ev mmModel.PluginClusterEvent) {
|
||||
p.wsPluginAdapter.HandleClusterEvent(ev)
|
||||
func (p *Plugin) OnPluginClusterEvent(ctx *plugin.Context, ev mm_model.PluginClusterEvent) {
|
||||
p.boardsApp.OnPluginClusterEvent(ctx, ev)
|
||||
}
|
||||
|
||||
func (p *Plugin) MessageWillBePosted(ctx *plugin.Context, post *mm_model.Post) (*mm_model.Post, string) {
|
||||
return p.boardsApp.MessageWillBePosted(ctx, post)
|
||||
}
|
||||
|
||||
func (p *Plugin) MessageWillBeUpdated(ctx *plugin.Context, newPost, oldPost *mm_model.Post) (*mm_model.Post, string) {
|
||||
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)
|
||||
}
|
||||
|
||||
// ServeHTTP demonstrates a plugin that handles HTTP requests by greeting the world.
|
||||
func (p *Plugin) ServeHTTP(_ *plugin.Context, w http.ResponseWriter, r *http.Request) {
|
||||
router := p.server.GetRootRouter()
|
||||
router.ServeHTTP(w, r)
|
||||
func (p *Plugin) ServeHTTP(ctx *plugin.Context, w http.ResponseWriter, r *http.Request) {
|
||||
p.boardsApp.ServeHTTP(ctx, w, r)
|
||||
}
|
||||
|
||||
func defaultLoggingConfig() string {
|
||||
@ -371,166 +147,3 @@ func defaultLoggingConfig() string {
|
||||
}
|
||||
}`
|
||||
}
|
||||
|
||||
func (p *Plugin) MessageWillBePosted(_ *plugin.Context, post *mmModel.Post) (*mmModel.Post, string) {
|
||||
return postWithBoardsEmbed(post), ""
|
||||
}
|
||||
|
||||
func (p *Plugin) MessageWillBeUpdated(_ *plugin.Context, newPost, _ *mmModel.Post) (*mmModel.Post, string) {
|
||||
return postWithBoardsEmbed(newPost), ""
|
||||
}
|
||||
|
||||
func postWithBoardsEmbed(post *mmModel.Post) *mmModel.Post {
|
||||
if _, ok := post.GetProps()["boards"]; ok {
|
||||
post.AddProp("boards", nil)
|
||||
}
|
||||
|
||||
firstLink, newPostMessage := getFirstLinkAndShortenAllBoardsLink(post.Message)
|
||||
post.Message = newPostMessage
|
||||
|
||||
if firstLink == "" {
|
||||
return post
|
||||
}
|
||||
|
||||
u, err := url.Parse(firstLink)
|
||||
|
||||
if err != nil {
|
||||
return post
|
||||
}
|
||||
|
||||
// Trim away the first / because otherwise after we split the string, the first element in the array is a empty element
|
||||
urlPath := u.Path
|
||||
urlPath = strings.TrimPrefix(urlPath, "/")
|
||||
urlPath = strings.TrimSuffix(urlPath, "/")
|
||||
pathSplit := strings.Split(strings.ToLower(urlPath), "/")
|
||||
queryParams := u.Query()
|
||||
|
||||
if len(pathSplit) == 0 {
|
||||
return post
|
||||
}
|
||||
|
||||
teamID, boardID, viewID, cardID := returnBoardsParams(pathSplit)
|
||||
|
||||
if teamID != "" && boardID != "" && viewID != "" && cardID != "" {
|
||||
b, _ := json.Marshal(BoardsEmbed{
|
||||
TeamID: teamID,
|
||||
BoardID: boardID,
|
||||
ViewID: viewID,
|
||||
CardID: cardID,
|
||||
ReadToken: queryParams.Get("r"),
|
||||
OriginalPath: u.RequestURI(),
|
||||
})
|
||||
|
||||
BoardsPostEmbed := &mmModel.PostEmbed{
|
||||
Type: mmModel.PostEmbedBoards,
|
||||
Data: string(b),
|
||||
}
|
||||
|
||||
if post.Metadata == nil {
|
||||
post.Metadata = &mmModel.PostMetadata{}
|
||||
}
|
||||
|
||||
post.Metadata.Embeds = []*mmModel.PostEmbed{BoardsPostEmbed}
|
||||
post.AddProp("boards", string(b))
|
||||
}
|
||||
|
||||
return post
|
||||
}
|
||||
|
||||
func getFirstLinkAndShortenAllBoardsLink(postMessage string) (firstLink, newPostMessage string) {
|
||||
newPostMessage = postMessage
|
||||
seenLinks := make(map[string]bool)
|
||||
markdown.Inspect(postMessage, func(blockOrInline interface{}) bool {
|
||||
if autoLink, ok := blockOrInline.(*markdown.Autolink); ok {
|
||||
link := autoLink.Destination()
|
||||
|
||||
if firstLink == "" {
|
||||
firstLink = link
|
||||
}
|
||||
|
||||
if seen := seenLinks[link]; !seen && isBoardsLink(link) {
|
||||
// TODO: Make sure that <Jump To Card> is Internationalized and translated to the Users Language preference
|
||||
markdownFormattedLink := fmt.Sprintf("[%s](%s)", "<Jump To Card>", link)
|
||||
newPostMessage = strings.ReplaceAll(newPostMessage, link, markdownFormattedLink)
|
||||
seenLinks[link] = true
|
||||
}
|
||||
}
|
||||
if inlineLink, ok := blockOrInline.(*markdown.InlineLink); ok {
|
||||
if link := inlineLink.Destination(); firstLink == "" {
|
||||
firstLink = link
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
return firstLink, newPostMessage
|
||||
}
|
||||
|
||||
func returnBoardsParams(pathArray []string) (teamID, boardID, viewID, cardID string) {
|
||||
// The reason we are doing this search for the first instance of boards or plugins is to take into account URL subpaths
|
||||
index := -1
|
||||
for i := 0; i < len(pathArray); i++ {
|
||||
if pathArray[i] == "boards" || pathArray[i] == "plugins" {
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if index == -1 {
|
||||
return teamID, boardID, viewID, cardID
|
||||
}
|
||||
|
||||
// If at index, the parameter in the path is boards,
|
||||
// then we've copied this directly as logged in user of that board
|
||||
|
||||
// If at index, the parameter in the path is plugins,
|
||||
// then we've copied this from a shared board
|
||||
|
||||
// For card links copied on a non-shared board, the path looks like {...Mattermost Url}.../boards/team/teamID/boardID/viewID/cardID
|
||||
|
||||
// For card links copied on a shared board, the path looks like
|
||||
// {...Mattermost Url}.../plugins/focalboard/team/teamID/shared/boardID/viewID/cardID?r=read_token
|
||||
|
||||
// This is a non-shared board card link
|
||||
if len(pathArray)-index == 6 && pathArray[index] == "boards" && pathArray[index+1] == "team" {
|
||||
teamID = pathArray[index+2]
|
||||
boardID = pathArray[index+3]
|
||||
viewID = pathArray[index+4]
|
||||
cardID = pathArray[index+5]
|
||||
} else if len(pathArray)-index == 8 && pathArray[index] == "plugins" &&
|
||||
pathArray[index+1] == "focalboard" &&
|
||||
pathArray[index+2] == "team" &&
|
||||
pathArray[index+4] == "shared" { // This is a shared board card link
|
||||
teamID = pathArray[index+3]
|
||||
boardID = pathArray[index+5]
|
||||
viewID = pathArray[index+6]
|
||||
cardID = pathArray[index+7]
|
||||
}
|
||||
return teamID, boardID, viewID, cardID
|
||||
}
|
||||
|
||||
func isBoardsLink(link string) bool {
|
||||
u, err := url.Parse(link)
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
urlPath := u.Path
|
||||
urlPath = strings.TrimPrefix(urlPath, "/")
|
||||
urlPath = strings.TrimSuffix(urlPath, "/")
|
||||
pathSplit := strings.Split(strings.ToLower(urlPath), "/")
|
||||
|
||||
if len(pathSplit) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
teamID, boardID, viewID, cardID := returnBoardsParams(pathSplit)
|
||||
return teamID != "" && boardID != "" && viewID != "" && cardID != ""
|
||||
}
|
||||
|
||||
func (p *Plugin) OnCloudLimitsUpdated(limits *mmModel.ProductLimits) {
|
||||
if err := p.server.App().SetCloudLimits(limits); err != nil {
|
||||
fmt.Println("Error setting the cloud limits for Boards", err)
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ type API struct {
|
||||
permissions permissions.PermissionsService
|
||||
singleUserToken string
|
||||
MattermostAuth bool
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
audit *audit.Audit
|
||||
isPlugin bool
|
||||
}
|
||||
@ -63,7 +63,7 @@ func NewAPI(
|
||||
singleUserToken string,
|
||||
authService string,
|
||||
permissions permissions.PermissionsService,
|
||||
logger *mlog.Logger,
|
||||
logger mlog.LoggerIFace,
|
||||
audit *audit.Audit,
|
||||
isPlugin bool,
|
||||
) *API {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -14,8 +15,7 @@ import (
|
||||
"github.com/mattermost/focalboard/server/utils"
|
||||
"github.com/mattermost/focalboard/server/ws"
|
||||
|
||||
mmModel "github.com/mattermost/mattermost-server/v6/model"
|
||||
|
||||
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"
|
||||
)
|
||||
@ -26,21 +26,32 @@ const (
|
||||
blockChangeNotifierShutdownTimeout = time.Second * 10
|
||||
)
|
||||
|
||||
type pluginAPI interface {
|
||||
GetUsers(options *mmModel.UserGetOptions) ([]*mmModel.User, *mmModel.AppError)
|
||||
type servicesAPI interface {
|
||||
GetUsersFromProfiles(options *mm_model.UserGetOptions) ([]*mm_model.User, error)
|
||||
}
|
||||
|
||||
type ReadCloseSeeker = filestore.ReadCloseSeeker
|
||||
|
||||
type fileBackend interface {
|
||||
Reader(path string) (ReadCloseSeeker, error)
|
||||
FileExists(path string) (bool, error)
|
||||
CopyFile(oldPath, newPath string) error
|
||||
MoveFile(oldPath, newPath string) error
|
||||
WriteFile(fr io.Reader, path string) (int64, error)
|
||||
RemoveFile(path string) error
|
||||
}
|
||||
|
||||
type Services struct {
|
||||
Auth *auth.Auth
|
||||
Store store.Store
|
||||
FilesBackend filestore.FileBackend
|
||||
FilesBackend fileBackend
|
||||
Webhook *webhook.Client
|
||||
Metrics *metrics.Metrics
|
||||
Notifications *notify.Service
|
||||
Logger *mlog.Logger
|
||||
Logger mlog.LoggerIFace
|
||||
Permissions permissions.PermissionsService
|
||||
SkipTemplateInit bool
|
||||
PluginAPI pluginAPI
|
||||
ServicesAPI servicesAPI
|
||||
}
|
||||
|
||||
type App struct {
|
||||
@ -48,13 +59,13 @@ type App struct {
|
||||
store store.Store
|
||||
auth *auth.Auth
|
||||
wsAdapter ws.Adapter
|
||||
filesBackend filestore.FileBackend
|
||||
filesBackend fileBackend
|
||||
webhook *webhook.Client
|
||||
metrics *metrics.Metrics
|
||||
notifications *notify.Service
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
blockChangeNotifier *utils.CallbackQueue
|
||||
pluginAPI pluginAPI
|
||||
servicesAPI servicesAPI
|
||||
|
||||
cardLimitMux sync.RWMutex
|
||||
cardLimit int
|
||||
@ -80,7 +91,7 @@ func New(config *config.Configuration, wsAdapter ws.Adapter, services Services)
|
||||
notifications: services.Notifications,
|
||||
logger: services.Logger,
|
||||
blockChangeNotifier: utils.NewCallbackQueue("blockChangeNotifier", blockChangeNotifierQueueSize, blockChangeNotifierPoolSize, services.Logger),
|
||||
pluginAPI: services.PluginAPI,
|
||||
servicesAPI: services.ServicesAPI,
|
||||
}
|
||||
app.initialize(services.SkipTemplateInit)
|
||||
return app
|
||||
|
@ -267,7 +267,7 @@ func (eb *errBoardNotFoundInTemplateMap) Error() string {
|
||||
}
|
||||
|
||||
func (a *App) NotifyPortalAdminsUpgradeRequest(teamID string) error {
|
||||
if a.pluginAPI == nil {
|
||||
if a.servicesAPI == nil {
|
||||
return ErrNilPluginAPI
|
||||
}
|
||||
|
||||
@ -295,7 +295,7 @@ func (a *App) NotifyPortalAdminsUpgradeRequest(teamID string) error {
|
||||
|
||||
for ; true; page++ {
|
||||
getUsersOptions.Page = page
|
||||
systemAdmins, appErr := a.pluginAPI.GetUsers(getUsersOptions)
|
||||
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
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"database/sql"
|
||||
"testing"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/plugin/plugintest"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
@ -16,6 +15,7 @@ import (
|
||||
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) {
|
||||
@ -649,7 +649,8 @@ func TestNotifyPortalAdminsUpgradeRequest(t *testing.T) {
|
||||
defer tearDown()
|
||||
|
||||
t.Run("should send message", func(t *testing.T) {
|
||||
pluginAPI := &plugintest.API{}
|
||||
ctrl := gomock.NewController(t)
|
||||
servicesAPI := mockservicesapi.NewMockServicesAPI(ctrl)
|
||||
|
||||
sysAdmin1 := &mmModel.User{
|
||||
Id: "michael-scott",
|
||||
@ -667,7 +668,7 @@ func TestNotifyPortalAdminsUpgradeRequest(t *testing.T) {
|
||||
PerPage: 50,
|
||||
Page: 0,
|
||||
}
|
||||
pluginAPI.On("GetUsers", getUsersOptionsPage0).Return([]*mmModel.User{sysAdmin1, sysAdmin2}, nil).Once()
|
||||
servicesAPI.EXPECT().GetUsersFromProfiles(getUsersOptionsPage0).Return([]*mmModel.User{sysAdmin1, sysAdmin2}, nil)
|
||||
|
||||
getUsersOptionsPage1 := &mmModel.UserGetOptions{
|
||||
Active: true,
|
||||
@ -675,9 +676,9 @@ func TestNotifyPortalAdminsUpgradeRequest(t *testing.T) {
|
||||
PerPage: 50,
|
||||
Page: 1,
|
||||
}
|
||||
pluginAPI.On("GetUsers", getUsersOptionsPage1).Return([]*mmModel.User{}, nil).Once()
|
||||
servicesAPI.EXPECT().GetUsersFromProfiles(getUsersOptionsPage1).Return([]*mmModel.User{}, nil)
|
||||
|
||||
th.App.pluginAPI = pluginAPI
|
||||
th.App.servicesAPI = servicesAPI
|
||||
|
||||
team := &model.Team{
|
||||
Title: "Dunder Mifflin",
|
||||
@ -691,7 +692,8 @@ func TestNotifyPortalAdminsUpgradeRequest(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("no sys admins found", func(t *testing.T) {
|
||||
pluginAPI := &plugintest.API{}
|
||||
ctrl := gomock.NewController(t)
|
||||
servicesAPI := mockservicesapi.NewMockServicesAPI(ctrl)
|
||||
|
||||
getUsersOptionsPage0 := &mmModel.UserGetOptions{
|
||||
Active: true,
|
||||
@ -699,9 +701,9 @@ func TestNotifyPortalAdminsUpgradeRequest(t *testing.T) {
|
||||
PerPage: 50,
|
||||
Page: 0,
|
||||
}
|
||||
pluginAPI.On("GetUsers", getUsersOptionsPage0).Return([]*mmModel.User{}, nil).Once()
|
||||
servicesAPI.EXPECT().GetUsersFromProfiles(getUsersOptionsPage0).Return([]*mmModel.User{}, nil)
|
||||
|
||||
th.App.pluginAPI = pluginAPI
|
||||
th.App.servicesAPI = servicesAPI
|
||||
|
||||
team := &model.Team{
|
||||
Title: "Dunder Mifflin",
|
||||
@ -714,7 +716,8 @@ func TestNotifyPortalAdminsUpgradeRequest(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("iterate multiple pages", func(t *testing.T) {
|
||||
pluginAPI := &plugintest.API{}
|
||||
ctrl := gomock.NewController(t)
|
||||
servicesAPI := mockservicesapi.NewMockServicesAPI(ctrl)
|
||||
|
||||
sysAdmin1 := &mmModel.User{
|
||||
Id: "michael-scott",
|
||||
@ -732,7 +735,7 @@ func TestNotifyPortalAdminsUpgradeRequest(t *testing.T) {
|
||||
PerPage: 50,
|
||||
Page: 0,
|
||||
}
|
||||
pluginAPI.On("GetUsers", getUsersOptionsPage0).Return([]*mmModel.User{sysAdmin1}, nil).Once()
|
||||
servicesAPI.EXPECT().GetUsersFromProfiles(getUsersOptionsPage0).Return([]*mmModel.User{sysAdmin1}, nil)
|
||||
|
||||
getUsersOptionsPage1 := &mmModel.UserGetOptions{
|
||||
Active: true,
|
||||
@ -740,7 +743,7 @@ func TestNotifyPortalAdminsUpgradeRequest(t *testing.T) {
|
||||
PerPage: 50,
|
||||
Page: 1,
|
||||
}
|
||||
pluginAPI.On("GetUsers", getUsersOptionsPage1).Return([]*mmModel.User{sysAdmin2}, nil).Once()
|
||||
servicesAPI.EXPECT().GetUsersFromProfiles(getUsersOptionsPage1).Return([]*mmModel.User{sysAdmin2}, nil)
|
||||
|
||||
getUsersOptionsPage2 := &mmModel.UserGetOptions{
|
||||
Active: true,
|
||||
@ -748,9 +751,9 @@ func TestNotifyPortalAdminsUpgradeRequest(t *testing.T) {
|
||||
PerPage: 50,
|
||||
Page: 2,
|
||||
}
|
||||
pluginAPI.On("GetUsers", getUsersOptionsPage2).Return([]*mmModel.User{}, nil).Once()
|
||||
servicesAPI.EXPECT().GetUsersFromProfiles(getUsersOptionsPage2).Return([]*mmModel.User{}, nil)
|
||||
|
||||
th.App.pluginAPI = pluginAPI
|
||||
th.App.servicesAPI = servicesAPI
|
||||
|
||||
team := &model.Team{
|
||||
Title: "Dunder Mifflin",
|
||||
|
@ -22,7 +22,7 @@ type TestHelper struct {
|
||||
App *App
|
||||
Store *mockstore.MockStore
|
||||
FilesBackend *mocks.FileBackend
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
}
|
||||
|
||||
func SetupTestHelper(t *testing.T) (*TestHelper, func()) {
|
||||
|
@ -2,8 +2,6 @@ module github.com/mattermost/focalboard/server
|
||||
|
||||
go 1.18
|
||||
|
||||
replace github.com/mattermost/mattermost-server/v6 => github.com/mattermost/mattermost-server/v6 v6.0.0-20220613202234-182ae1234a49
|
||||
|
||||
require (
|
||||
github.com/Masterminds/squirrel v1.5.2
|
||||
github.com/go-sql-driver/mysql v1.6.0
|
||||
@ -11,9 +9,9 @@ require (
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/krolaw/zipstream v0.0.0-20180621105154-0a2661891f94
|
||||
github.com/lib/pq v1.10.5
|
||||
github.com/mattermost/mattermost-plugin-api v0.0.27
|
||||
github.com/mattermost/mattermost-server/v6 v6.3.0
|
||||
github.com/lib/pq v1.10.6
|
||||
github.com/mattermost/mattermost-plugin-api v0.0.28-0.20220623051512-0afd85e854d4
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220711175838-7ee7523729e6
|
||||
github.com/mattermost/morph v0.0.0-20220401091636-39f834798da8
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
||||
github.com/oklog/run v1.1.0
|
||||
@ -22,15 +20,14 @@ require (
|
||||
github.com/rudderlabs/analytics-go v3.3.2+incompatible
|
||||
github.com/sergi/go-diff v1.2.0
|
||||
github.com/spf13/viper v1.10.1
|
||||
github.com/stretchr/testify v1.7.1
|
||||
github.com/stretchr/testify v1.7.2
|
||||
github.com/wiggin77/merror v1.0.3
|
||||
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
@ -42,14 +39,14 @@ require (
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/graph-gophers/graphql-go v1.4.0 // indirect
|
||||
github.com/hashicorp/go-hclog v1.2.0 // indirect
|
||||
github.com/hashicorp/go-hclog v1.2.1 // indirect
|
||||
github.com/hashicorp/go-plugin v1.4.4 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // 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.3 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.12 // indirect
|
||||
github.com/klauspost/compress v1.15.6 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.13 // 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
|
||||
@ -60,7 +57,7 @@ require (
|
||||
github.com/mattn/go-isatty v0.0.14 // 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.26 // indirect
|
||||
github.com/minio/minio-go/v7 v7.0.28 // indirect
|
||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
@ -72,7 +69,7 @@ require (
|
||||
github.com/philhofer/fwd v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
github.com/prometheus/common v0.33.0 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
github.com/rs/xid v1.4.0 // indirect
|
||||
@ -93,19 +90,18 @@ require (
|
||||
github.com/wiggin77/srslog v1.0.1 // indirect
|
||||
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect
|
||||
github.com/yuin/goldmark v1.4.12 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // 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/tools v0.1.10 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect
|
||||
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3 // indirect
|
||||
google.golang.org/grpc v1.46.0 // indirect
|
||||
golang.org/x/tools v0.1.11 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220614165028-45ed7f3ff16e // indirect
|
||||
google.golang.org/grpc v1.47.0 // indirect
|
||||
google.golang.org/protobuf v1.28.0 // indirect
|
||||
gopkg.in/ini.v1 v1.66.4 // indirect
|
||||
gopkg.in/ini.v1 v1.66.6 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lukechampine.com/uint128 v1.2.0 // indirect
|
||||
modernc.org/cc/v3 v3.35.24 // indirect
|
||||
modernc.org/ccgo/v3 v3.15.17 // indirect
|
||||
|
@ -130,6 +130,7 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/RoaringBitmap/roaring v0.9.4/go.mod h1:icnadbWcNyfEHlYdr+tDlOTih1Bf/h+rzPpv4sbomAA=
|
||||
github.com/RoaringBitmap/roaring v1.2.1/go.mod h1:icnadbWcNyfEHlYdr+tDlOTih1Bf/h+rzPpv4sbomAA=
|
||||
github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
|
||||
github.com/advancedlogic/GoOse v0.0.0-20191112112754-e742535969c1/go.mod h1:f3HCSN1fBWjcpGtXyM119MJgeQl838v6so/PQOqvE1w=
|
||||
@ -164,7 +165,7 @@ github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:l
|
||||
github.com/avct/uasurfer v0.0.0-20191028135549-26b5daa857f1/go.mod h1:noBAuukeYOXa0aXGqxr24tADqkwDO2KRD15FsuaZ5a8=
|
||||
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
|
||||
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.44.9/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go v1.44.34/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go-v2 v1.8.0/go.mod h1:xEFuWz+3TYdlPRuo+CqATbeDWIWyaT5uAPwPaWtgse0=
|
||||
github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.6.0/go.mod h1:TNtBVmka80lRPk5+S9ZqVfFszOQAGJJ9KbT3EM3CHNU=
|
||||
@ -210,27 +211,34 @@ github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqO
|
||||
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
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/blevesearch/bleve/v2 v2.3.2/go.mod h1:96+xE5pZUOsr3Y4vHzV1cBC837xZCpwLlX0hrrxnvIg=
|
||||
github.com/blevesearch/bleve_index_api v1.0.1/go.mod h1:fiwKS0xLEm+gBRgv5mumf0dhgFr2mDgZah1pqv1c1M4=
|
||||
github.com/blevesearch/bleve_index_api v1.0.2/go.mod h1:fiwKS0xLEm+gBRgv5mumf0dhgFr2mDgZah1pqv1c1M4=
|
||||
github.com/blevesearch/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:9eJDeqxJ3E7WnLebQUlPD7ZjSce7AnDb9vjGmMCbD0A=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
|
||||
github.com/blevesearch/goleveldb v1.0.1/go.mod h1:WrU8ltZbIp0wAoig/MHbrPCXSOLpe79nz5lv5nqfYrQ=
|
||||
github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk=
|
||||
github.com/blevesearch/mmap-go v1.0.2/go.mod h1:ol2qBqYaOUsGdm7aRMRrYGgPvnwLe6Y+7LMvAB5IbSA=
|
||||
github.com/blevesearch/mmap-go v1.0.3/go.mod h1:pYvKl/grLQrBxuaRYgoTssa4rVujYYeenDp++2E+yvs=
|
||||
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.1.0/go.mod h1:uch7xyyO/Alxkuxa+CGs79vw0QY8BENSBjg6Mw5L5DE=
|
||||
github.com/blevesearch/segment v0.9.0/go.mod h1:9PfHYUdQCgHktBgvtUOF4x+pc4/l8rdH0u5spnW85UQ=
|
||||
github.com/blevesearch/snowball v0.6.1/go.mod h1:ZF0IBg5vgpeoUhnMza2v0A/z8m1cWPlwhke08LpNusg=
|
||||
github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs=
|
||||
github.com/blevesearch/upsidedown_store_api v1.0.1/go.mod h1:MQDVGpHZrpe3Uy26zJBf/a8h0FZY6xJbthIMm8myH2Q=
|
||||
github.com/blevesearch/vellum v1.0.7/go.mod h1:doBZpmRhwTsASB4QdUZANlJvqVAUdUyX0ZK7QJCTeBE=
|
||||
github.com/blevesearch/vellum v1.0.8/go.mod h1:+cpRi/tqq49xUYSQN2P7A5zNSNrS+MscLeeaZ3J46UA=
|
||||
github.com/blevesearch/zapx/v11 v11.3.3/go.mod h1:YzTfUm4kS3e8OmTXDHVV8OzC5MWPO/VPJZQgPNVb4Lc=
|
||||
github.com/blevesearch/zapx/v11 v11.3.4/go.mod h1:HJ7qdfBxdziuymKvXbsBVhCK5pB98tdzQbc8pJV6tJo=
|
||||
github.com/blevesearch/zapx/v12 v12.3.3/go.mod h1:RMl6lOZqF+sTxKvhQDJ5yK2LT3Mu7E2p/jGdjAaiRxs=
|
||||
github.com/blevesearch/zapx/v12 v12.3.4/go.mod h1:uQrKrK9XjXAAsJfAIE8ViLqIKP/keA2DQhS1XXpjkwA=
|
||||
github.com/blevesearch/zapx/v13 v13.3.3/go.mod h1:eppobNM35U4C22yDvTuxV9xPqo10pwfP/jugL4INWG4=
|
||||
github.com/blevesearch/zapx/v13 v13.3.4/go.mod h1:Wl7hO1gT+IDvJb7i06g2iW5Qvw0KzncJPsBx7WGWhLA=
|
||||
github.com/blevesearch/zapx/v14 v14.3.3/go.mod h1:zXNcVzukh0AvG57oUtT1T0ndi09H0kELNaNmekEy0jw=
|
||||
github.com/blevesearch/zapx/v14 v14.3.4/go.mod h1:b1YhRXXhAj9i+9aOwhRKCHUmJyYieK/QbDvPJDLddUk=
|
||||
github.com/blevesearch/zapx/v15 v15.3.3/go.mod h1:C+f/97ZzTzK6vt/7sVlZdzZxKu+5+j4SrGCvr9dJzaY=
|
||||
github.com/blevesearch/zapx/v15 v15.3.4/go.mod h1:TQ/qDC2q7TSSpeC6Vgr9fDN56Ra0u49lZJQ4v30WEx4=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
@ -526,10 +534,12 @@ github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3I
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||
github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
@ -767,8 +777,8 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM=
|
||||
github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw=
|
||||
github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
|
||||
@ -920,16 +930,16 @@ github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8
|
||||
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.3 h1:wmfu2iqj9q22SyMINp1uQ8C2/V4M1phJdmH9fG4nba0=
|
||||
github.com/klauspost/compress v1.15.3/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY=
|
||||
github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
|
||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.0.13 h1:1XxvOiqXZ8SULZUKim/wncr3wZ38H4yCuVDvKdK9OGs=
|
||||
github.com/klauspost/cpuid/v2 v2.0.13/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@ -966,9 +976,8 @@ github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.5 h1:J+gdV2cUmX7ZqL2B0lFcW0m+egaHC2V3lpO8nWxyYiQ=
|
||||
github.com/lib/pq v1.10.5/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs=
|
||||
github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
|
||||
@ -994,10 +1003,11 @@ github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d h1:/RJ/UV7M5c7L2TQ
|
||||
github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d/go.mod h1:HLbgMEI5K131jpxGazJ97AxfPDt31osq36YS1oxFQPQ=
|
||||
github.com/mattermost/logr/v2 v2.0.15 h1:+WNbGcsc3dBao65eXlceB6dTILNJRIrvubnsTl3zBew=
|
||||
github.com/mattermost/logr/v2 v2.0.15/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg=
|
||||
github.com/mattermost/mattermost-plugin-api v0.0.27 h1:zFKQ6JW1/f0MfR5dP9P2umNNYVcLtTO74mM/PrVPNC4=
|
||||
github.com/mattermost/mattermost-plugin-api v0.0.27/go.mod h1:MM+tZ+36Obm9jqcveoxY2RFbwLaZKZUgR1zUlc0UBYw=
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220613202234-182ae1234a49 h1:7uFRdTX54qUp7jNodn0+vrhxuwnudHxWRv7kLN72Fig=
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220613202234-182ae1234a49/go.mod h1:HBSu5YC0k8TLb+7DFFB9/63/+oBZj7pgx8K07lHmzyI=
|
||||
github.com/mattermost/mattermost-plugin-api v0.0.28-0.20220623051512-0afd85e854d4 h1:TF1yBBsLntuNb3wc3DRg30S9i6tv1JwtREtXd7Gnv9E=
|
||||
github.com/mattermost/mattermost-plugin-api v0.0.28-0.20220623051512-0afd85e854d4/go.mod h1:jtiaM6selJi1Od1zGZDGO78hZyG0gI4/I2/8mza4OZg=
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220622145221-00016e3a4ff4/go.mod h1:e2CtTtnty6oH8CiHm40cMOqJ+dJeWEK39/tobCkeMAk=
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220711175838-7ee7523729e6 h1:lfkO5s/ZwuD2esAHGX+0EtmcsAVXJ0S5Xn37uWW/WoQ=
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0-20220711175838-7ee7523729e6/go.mod h1:e2CtTtnty6oH8CiHm40cMOqJ+dJeWEK39/tobCkeMAk=
|
||||
github.com/mattermost/morph v0.0.0-20220401091636-39f834798da8 h1:gwliVjCTqAC01mSCNqa5nJ/4MmGq50vrjsottIhQ4d8=
|
||||
github.com/mattermost/morph v0.0.0-20220401091636-39f834798da8/go.mod h1:jxM3g1bx+k2Thz7jofcHguBS8TZn5Pc+o5MGmORObhw=
|
||||
github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0/go.mod h1:nV5bfVpT//+B1RPD2JvRnxbkLmJEYXmRaaVl15fsXjs=
|
||||
@ -1053,8 +1063,8 @@ github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WT
|
||||
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
|
||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.26 h1:D0HK+8793etZfRY/vHhDmFaP+vmT41K3K4JV9vmZCBQ=
|
||||
github.com/minio/minio-go/v7 v7.0.26/go.mod h1:x81+AX5gHSfCSqw7jxRKHvxUXMlE5uKX0Vb75Xk5yYg=
|
||||
github.com/minio/minio-go/v7 v7.0.28 h1:VMr3K5qGIEt+/KW3poopRh8mzi5RwuCjmrmstK196Fg=
|
||||
github.com/minio/minio-go/v7 v7.0.28/go.mod h1:x81+AX5gHSfCSqw7jxRKHvxUXMlE5uKX0Vb75Xk5yYg=
|
||||
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
|
||||
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
|
||||
@ -1254,8 +1264,9 @@ github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
|
||||
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/common v0.33.0 h1:rHgav/0a6+uYgGdNt3jwz8FNSesO/Hsang3O0T9A5SE=
|
||||
github.com/prometheus/common v0.33.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE=
|
||||
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
@ -1295,7 +1306,6 @@ github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
|
||||
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
github.com/rudderlabs/analytics-go v3.3.1+incompatible/go.mod h1:LF8/ty9kUX4PTY3l5c97K3nZZaX5Hwsvt+NBaRL/f30=
|
||||
github.com/rudderlabs/analytics-go v3.3.2+incompatible h1:bDajEJTYhfHjNYxbQFMA/2dHlOjyeSgxS7GPIdMZ52Q=
|
||||
github.com/rudderlabs/analytics-go v3.3.2+incompatible/go.mod h1:LF8/ty9kUX4PTY3l5c97K3nZZaX5Hwsvt+NBaRL/f30=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
@ -1420,8 +1430,9 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
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 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||
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/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
@ -1608,8 +1619,8 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 h1:NvGWuYG8dkDHFSKksI1P9faiVJ9rayE6l0+ouWVIDs8=
|
||||
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
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/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@ -1635,7 +1646,7 @@ golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+o
|
||||
golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
||||
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=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
@ -1662,8 +1673,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -1742,8 +1753,8 @@ golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/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/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@ -1765,6 +1776,7 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ
|
||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -1778,6 +1790,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -1910,8 +1923,10 @@ golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 h1:PgOr27OhUx2IRqGJ2RxAWI4dJQ7bi9cSrB82uzFzfUA=
|
||||
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
@ -2021,16 +2036,16 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20=
|
||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||
golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
|
||||
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U=
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0=
|
||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
||||
gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
|
||||
gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0=
|
||||
@ -2161,8 +2176,8 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6
|
||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
||||
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3 h1:q1kiSVscqoDeqTF27eQ2NnLLDmqF0I373qQNXYMy0fo=
|
||||
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||
google.golang.org/genproto v0.0.0-20220614165028-45ed7f3ff16e h1:ubR4JUtqN3ffdFjpKylv8scWk/mZstGmzXbgYSkuMl0=
|
||||
google.golang.org/genproto v0.0.0-20220614165028-45ed7f3ff16e/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
@ -2200,8 +2215,8 @@ google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K
|
||||
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||
google.golang.org/grpc v1.46.0 h1:oCjezcn6g6A75TGoKYBPgKmVBLexhYLM6MebdrPApP8=
|
||||
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
|
||||
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
@ -2238,8 +2253,8 @@ gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4=
|
||||
gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI=
|
||||
gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
@ -2264,8 +2279,9 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/postgres v1.0.8/go.mod h1:4eOzrI1MUfm6ObJU/UcmbXyiHSs8jSwH95G5P5dxcAg=
|
||||
gorm.io/gorm v1.20.12/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
gorm.io/gorm v1.21.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
|
@ -67,7 +67,6 @@ type TestHelper struct {
|
||||
|
||||
type FakePermissionPluginAPI struct{}
|
||||
|
||||
func (*FakePermissionPluginAPI) LogError(str string, params ...interface{}) {}
|
||||
func (*FakePermissionPluginAPI) HasPermissionToTeam(userID string, teamID string, permission *mmModel.Permission) bool {
|
||||
if userID == userNoTeamMember {
|
||||
return false
|
||||
@ -195,7 +194,7 @@ func NewTestServerPluginMode() *server.Server {
|
||||
|
||||
db := NewPluginTestStore(innerStore)
|
||||
|
||||
permissionsService := mmpermissions.New(db, &FakePermissionPluginAPI{})
|
||||
permissionsService := mmpermissions.New(db, &FakePermissionPluginAPI{}, logger)
|
||||
|
||||
params := server.Params{
|
||||
Cfg: cfg,
|
||||
@ -345,7 +344,11 @@ func (th *TestHelper) InitBasic() *TestHelper {
|
||||
var ErrRegisterFail = errors.New("register failed")
|
||||
|
||||
func (th *TestHelper) TearDown() {
|
||||
defer func() { _ = th.Server.Logger().Shutdown() }()
|
||||
logger := th.Server.Logger()
|
||||
|
||||
if l, ok := logger.(*mlog.Logger); ok {
|
||||
defer func() { _ = l.Shutdown() }()
|
||||
}
|
||||
|
||||
err := th.Server.Shutdown()
|
||||
if err != nil {
|
||||
@ -355,7 +358,7 @@ func (th *TestHelper) TearDown() {
|
||||
os.RemoveAll(th.Server.Config().FilesPath)
|
||||
|
||||
if err := os.Remove(th.Server.Config().DBConfigString); err == nil {
|
||||
th.Server.Logger().Debug("Removed test database", mlog.String("file", th.Server.Config().DBConfigString))
|
||||
logger.Debug("Removed test database", mlog.String("file", th.Server.Config().DBConfigString))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,11 +263,16 @@ func stopServer() {
|
||||
return
|
||||
}
|
||||
|
||||
logger := pServer.Logger()
|
||||
|
||||
err := pServer.Shutdown()
|
||||
if err != nil {
|
||||
pServer.Logger().Error("server.Shutdown ERROR", mlog.Err(err))
|
||||
logger.Error("server.Shutdown ERROR", mlog.Err(err))
|
||||
}
|
||||
|
||||
if l, ok := logger.(*mlog.Logger); ok {
|
||||
_ = l.Shutdown()
|
||||
}
|
||||
_ = pServer.Logger().Shutdown()
|
||||
pServer = nil
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
// keeping consistent any references that other blocks would made to
|
||||
// the original IDs, so a tree of blocks can get new IDs and maintain
|
||||
// its shape.
|
||||
func GenerateBlockIDs(blocks []Block, logger *mlog.Logger) []Block {
|
||||
func GenerateBlockIDs(blocks []Block, logger mlog.LoggerIFace) []Block {
|
||||
blockIDs := map[string]BlockType{}
|
||||
referenceIDs := map[string]bool{}
|
||||
for _, block := range blocks {
|
||||
@ -99,7 +99,7 @@ func GenerateBlockIDs(blocks []Block, logger *mlog.Logger) []Block {
|
||||
return newBlocks
|
||||
}
|
||||
|
||||
func fixFieldIDs(block *Block, fieldName string, getExistingOrOldID func(string) string, logger *mlog.Logger) {
|
||||
func fixFieldIDs(block *Block, fieldName string, getExistingOrOldID func(string) string, logger mlog.LoggerIFace) {
|
||||
field, typeOk := block.Fields[fieldName].([]interface{})
|
||||
if !typeOk {
|
||||
logger.Warn(
|
||||
|
@ -134,7 +134,7 @@ func (dbab *PatchBoardsAndBlocks) IsValid() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GenerateBoardsAndBlocksIDs(bab *BoardsAndBlocks, logger *mlog.Logger) (*BoardsAndBlocks, error) {
|
||||
func GenerateBoardsAndBlocksIDs(bab *BoardsAndBlocks, logger mlog.LoggerIFace) (*BoardsAndBlocks, error) {
|
||||
if err := bab.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
402
server/model/mocks/mockservicesapi.go
Normal file
402
server/model/mocks/mockservicesapi.go
Normal file
@ -0,0 +1,402 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/mattermost/focalboard/server/model (interfaces: ServicesAPI)
|
||||
|
||||
// Package mocks is a generated GoMock package.
|
||||
package mocks
|
||||
|
||||
import (
|
||||
sql "database/sql"
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
model "github.com/mattermost/mattermost-server/v6/model"
|
||||
mlog "github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
// MockServicesAPI is a mock of ServicesAPI interface.
|
||||
type MockServicesAPI struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockServicesAPIMockRecorder
|
||||
}
|
||||
|
||||
// MockServicesAPIMockRecorder is the mock recorder for MockServicesAPI.
|
||||
type MockServicesAPIMockRecorder struct {
|
||||
mock *MockServicesAPI
|
||||
}
|
||||
|
||||
// NewMockServicesAPI creates a new mock instance.
|
||||
func NewMockServicesAPI(ctrl *gomock.Controller) *MockServicesAPI {
|
||||
mock := &MockServicesAPI{ctrl: ctrl}
|
||||
mock.recorder = &MockServicesAPIMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockServicesAPI) EXPECT() *MockServicesAPIMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// CreateMember mocks base method.
|
||||
func (m *MockServicesAPI) CreateMember(arg0, arg1 string) (*model.TeamMember, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreateMember", arg0, arg1)
|
||||
ret0, _ := ret[0].(*model.TeamMember)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CreateMember indicates an expected call of CreateMember.
|
||||
func (mr *MockServicesAPIMockRecorder) CreateMember(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateMember", reflect.TypeOf((*MockServicesAPI)(nil).CreateMember), arg0, arg1)
|
||||
}
|
||||
|
||||
// CreatePost mocks base method.
|
||||
func (m *MockServicesAPI) CreatePost(arg0 *model.Post) (*model.Post, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreatePost", arg0)
|
||||
ret0, _ := ret[0].(*model.Post)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CreatePost indicates an expected call of CreatePost.
|
||||
func (mr *MockServicesAPIMockRecorder) CreatePost(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreatePost", reflect.TypeOf((*MockServicesAPI)(nil).CreatePost), arg0)
|
||||
}
|
||||
|
||||
// EnsureBot mocks base method.
|
||||
func (m *MockServicesAPI) EnsureBot(arg0 *model.Bot) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EnsureBot", arg0)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EnsureBot indicates an expected call of EnsureBot.
|
||||
func (mr *MockServicesAPIMockRecorder) EnsureBot(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnsureBot", reflect.TypeOf((*MockServicesAPI)(nil).EnsureBot), arg0)
|
||||
}
|
||||
|
||||
// GetChannelByID mocks base method.
|
||||
func (m *MockServicesAPI) GetChannelByID(arg0 string) (*model.Channel, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetChannelByID", arg0)
|
||||
ret0, _ := ret[0].(*model.Channel)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetChannelByID indicates an expected call of GetChannelByID.
|
||||
func (mr *MockServicesAPIMockRecorder) GetChannelByID(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChannelByID", reflect.TypeOf((*MockServicesAPI)(nil).GetChannelByID), arg0)
|
||||
}
|
||||
|
||||
// GetChannelMember mocks base method.
|
||||
func (m *MockServicesAPI) GetChannelMember(arg0, arg1 string) (*model.ChannelMember, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetChannelMember", arg0, arg1)
|
||||
ret0, _ := ret[0].(*model.ChannelMember)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetChannelMember indicates an expected call of GetChannelMember.
|
||||
func (mr *MockServicesAPIMockRecorder) GetChannelMember(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChannelMember", reflect.TypeOf((*MockServicesAPI)(nil).GetChannelMember), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetChannelsForTeamForUser mocks base method.
|
||||
func (m *MockServicesAPI) GetChannelsForTeamForUser(arg0, arg1 string, arg2 bool) (model.ChannelList, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetChannelsForTeamForUser", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(model.ChannelList)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetChannelsForTeamForUser indicates an expected call of GetChannelsForTeamForUser.
|
||||
func (mr *MockServicesAPIMockRecorder) GetChannelsForTeamForUser(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
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()
|
||||
ret := m.ctrl.Call(m, "GetConfig")
|
||||
ret0, _ := ret[0].(*model.Config)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetConfig indicates an expected call of GetConfig.
|
||||
func (mr *MockServicesAPIMockRecorder) GetConfig() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConfig", reflect.TypeOf((*MockServicesAPI)(nil).GetConfig))
|
||||
}
|
||||
|
||||
// GetDiagnosticID mocks base method.
|
||||
func (m *MockServicesAPI) GetDiagnosticID() string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetDiagnosticID")
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetDiagnosticID indicates an expected call of GetDiagnosticID.
|
||||
func (mr *MockServicesAPIMockRecorder) GetDiagnosticID() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDiagnosticID", reflect.TypeOf((*MockServicesAPI)(nil).GetDiagnosticID))
|
||||
}
|
||||
|
||||
// GetDirectChannel mocks base method.
|
||||
func (m *MockServicesAPI) GetDirectChannel(arg0, arg1 string) (*model.Channel, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetDirectChannel", arg0, arg1)
|
||||
ret0, _ := ret[0].(*model.Channel)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetDirectChannel indicates an expected call of GetDirectChannel.
|
||||
func (mr *MockServicesAPIMockRecorder) GetDirectChannel(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDirectChannel", reflect.TypeOf((*MockServicesAPI)(nil).GetDirectChannel), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetFileInfo mocks base method.
|
||||
func (m *MockServicesAPI) GetFileInfo(arg0 string) (*model.FileInfo, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetFileInfo", arg0)
|
||||
ret0, _ := ret[0].(*model.FileInfo)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetFileInfo indicates an expected call of GetFileInfo.
|
||||
func (mr *MockServicesAPIMockRecorder) GetFileInfo(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFileInfo", reflect.TypeOf((*MockServicesAPI)(nil).GetFileInfo), arg0)
|
||||
}
|
||||
|
||||
// GetLicense mocks base method.
|
||||
func (m *MockServicesAPI) GetLicense() *model.License {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetLicense")
|
||||
ret0, _ := ret[0].(*model.License)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetLicense indicates an expected call of GetLicense.
|
||||
func (mr *MockServicesAPIMockRecorder) GetLicense() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLicense", reflect.TypeOf((*MockServicesAPI)(nil).GetLicense))
|
||||
}
|
||||
|
||||
// GetLogger mocks base method.
|
||||
func (m *MockServicesAPI) GetLogger() mlog.LoggerIFace {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetLogger")
|
||||
ret0, _ := ret[0].(mlog.LoggerIFace)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetLogger indicates an expected call of GetLogger.
|
||||
func (mr *MockServicesAPIMockRecorder) GetLogger() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLogger", reflect.TypeOf((*MockServicesAPI)(nil).GetLogger))
|
||||
}
|
||||
|
||||
// GetMasterDB mocks base method.
|
||||
func (m *MockServicesAPI) GetMasterDB() (*sql.DB, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetMasterDB")
|
||||
ret0, _ := ret[0].(*sql.DB)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetMasterDB indicates an expected call of GetMasterDB.
|
||||
func (mr *MockServicesAPIMockRecorder) GetMasterDB() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMasterDB", reflect.TypeOf((*MockServicesAPI)(nil).GetMasterDB))
|
||||
}
|
||||
|
||||
// GetTeamMember mocks base method.
|
||||
func (m *MockServicesAPI) GetTeamMember(arg0, arg1 string) (*model.TeamMember, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetTeamMember", arg0, arg1)
|
||||
ret0, _ := ret[0].(*model.TeamMember)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetTeamMember indicates an expected call of GetTeamMember.
|
||||
func (mr *MockServicesAPIMockRecorder) GetTeamMember(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTeamMember", reflect.TypeOf((*MockServicesAPI)(nil).GetTeamMember), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetUserByEmail mocks base method.
|
||||
func (m *MockServicesAPI) GetUserByEmail(arg0 string) (*model.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetUserByEmail", arg0)
|
||||
ret0, _ := ret[0].(*model.User)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetUserByEmail indicates an expected call of GetUserByEmail.
|
||||
func (mr *MockServicesAPIMockRecorder) GetUserByEmail(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserByEmail", reflect.TypeOf((*MockServicesAPI)(nil).GetUserByEmail), arg0)
|
||||
}
|
||||
|
||||
// GetUserByID mocks base method.
|
||||
func (m *MockServicesAPI) GetUserByID(arg0 string) (*model.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetUserByID", arg0)
|
||||
ret0, _ := ret[0].(*model.User)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetUserByID indicates an expected call of GetUserByID.
|
||||
func (mr *MockServicesAPIMockRecorder) GetUserByID(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserByID", reflect.TypeOf((*MockServicesAPI)(nil).GetUserByID), arg0)
|
||||
}
|
||||
|
||||
// GetUserByUsername mocks base method.
|
||||
func (m *MockServicesAPI) GetUserByUsername(arg0 string) (*model.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetUserByUsername", arg0)
|
||||
ret0, _ := ret[0].(*model.User)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetUserByUsername indicates an expected call of GetUserByUsername.
|
||||
func (mr *MockServicesAPIMockRecorder) GetUserByUsername(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserByUsername", reflect.TypeOf((*MockServicesAPI)(nil).GetUserByUsername), arg0)
|
||||
}
|
||||
|
||||
// GetUsersFromProfiles mocks base method.
|
||||
func (m *MockServicesAPI) GetUsersFromProfiles(arg0 *model.UserGetOptions) ([]*model.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetUsersFromProfiles", arg0)
|
||||
ret0, _ := ret[0].([]*model.User)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetUsersFromProfiles indicates an expected call of GetUsersFromProfiles.
|
||||
func (mr *MockServicesAPIMockRecorder) GetUsersFromProfiles(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUsersFromProfiles", reflect.TypeOf((*MockServicesAPI)(nil).GetUsersFromProfiles), arg0)
|
||||
}
|
||||
|
||||
// HasPermissionToChannel mocks base method.
|
||||
func (m *MockServicesAPI) HasPermissionToChannel(arg0, arg1 string, arg2 *model.Permission) bool {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HasPermissionToChannel", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(bool)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// HasPermissionToChannel indicates an expected call of HasPermissionToChannel.
|
||||
func (mr *MockServicesAPIMockRecorder) HasPermissionToChannel(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasPermissionToChannel", reflect.TypeOf((*MockServicesAPI)(nil).HasPermissionToChannel), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// HasPermissionToTeam mocks base method.
|
||||
func (m *MockServicesAPI) HasPermissionToTeam(arg0, arg1 string, arg2 *model.Permission) bool {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HasPermissionToTeam", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(bool)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// HasPermissionToTeam indicates an expected call of HasPermissionToTeam.
|
||||
func (mr *MockServicesAPIMockRecorder) HasPermissionToTeam(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasPermissionToTeam", reflect.TypeOf((*MockServicesAPI)(nil).HasPermissionToTeam), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// KVSetWithOptions mocks base method.
|
||||
func (m *MockServicesAPI) KVSetWithOptions(arg0 string, arg1 []byte, arg2 model.PluginKVSetOptions) (bool, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "KVSetWithOptions", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(bool)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// KVSetWithOptions indicates an expected call of KVSetWithOptions.
|
||||
func (mr *MockServicesAPIMockRecorder) KVSetWithOptions(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KVSetWithOptions", reflect.TypeOf((*MockServicesAPI)(nil).KVSetWithOptions), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// PublishPluginClusterEvent mocks base method.
|
||||
func (m *MockServicesAPI) PublishPluginClusterEvent(arg0 model.PluginClusterEvent, arg1 model.PluginClusterEventSendOptions) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PublishPluginClusterEvent", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// PublishPluginClusterEvent indicates an expected call of PublishPluginClusterEvent.
|
||||
func (mr *MockServicesAPIMockRecorder) PublishPluginClusterEvent(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublishPluginClusterEvent", reflect.TypeOf((*MockServicesAPI)(nil).PublishPluginClusterEvent), arg0, arg1)
|
||||
}
|
||||
|
||||
// PublishWebSocketEvent mocks base method.
|
||||
func (m *MockServicesAPI) PublishWebSocketEvent(arg0 string, arg1 map[string]interface{}, arg2 *model.WebsocketBroadcast) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "PublishWebSocketEvent", arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// PublishWebSocketEvent indicates an expected call of PublishWebSocketEvent.
|
||||
func (mr *MockServicesAPIMockRecorder) PublishWebSocketEvent(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublishWebSocketEvent", reflect.TypeOf((*MockServicesAPI)(nil).PublishWebSocketEvent), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// UpdateUser mocks base method.
|
||||
func (m *MockServicesAPI) UpdateUser(arg0 *model.User) (*model.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateUser", arg0)
|
||||
ret0, _ := ret[0].(*model.User)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdateUser indicates an expected call of UpdateUser.
|
||||
func (mr *MockServicesAPIMockRecorder) UpdateUser(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUser", reflect.TypeOf((*MockServicesAPI)(nil).UpdateUser), arg0)
|
||||
}
|
70
server/model/services_api.go
Normal file
70
server/model/services_api.go
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
//go:generate mockgen --build_flags= -destination=mocks/mockservicesapi.go -package mocks . ServicesAPI
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
mm_model "github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
type ServicesAPI interface {
|
||||
// Channels service
|
||||
GetDirectChannel(userID1, userID2 string) (*mm_model.Channel, error)
|
||||
GetChannelByID(channelID string) (*mm_model.Channel, error)
|
||||
GetChannelMember(channelID string, userID string) (*mm_model.ChannelMember, error)
|
||||
GetChannelsForTeamForUser(teamID string, userID string, includeDeleted bool) (mm_model.ChannelList, error)
|
||||
|
||||
// Post service
|
||||
CreatePost(post *mm_model.Post) (*mm_model.Post, error)
|
||||
|
||||
// User service
|
||||
GetUserByID(userID string) (*mm_model.User, error)
|
||||
GetUserByUsername(name string) (*mm_model.User, error)
|
||||
GetUserByEmail(email string) (*mm_model.User, error)
|
||||
UpdateUser(user *mm_model.User) (*mm_model.User, error)
|
||||
GetUsersFromProfiles(options *mm_model.UserGetOptions) ([]*mm_model.User, error)
|
||||
|
||||
// Team service
|
||||
GetTeamMember(teamID string, userID string) (*mm_model.TeamMember, error)
|
||||
CreateMember(teamID string, userID string) (*mm_model.TeamMember, error)
|
||||
|
||||
// Permissions service
|
||||
HasPermissionToTeam(userID, teamID string, permission *mm_model.Permission) bool
|
||||
HasPermissionToChannel(askingUserID string, channelID string, permission *mm_model.Permission) bool
|
||||
|
||||
// Bot service
|
||||
EnsureBot(bot *mm_model.Bot) (string, error)
|
||||
|
||||
// License service
|
||||
GetLicense() *mm_model.License
|
||||
|
||||
// FileInfoStore service
|
||||
GetFileInfo(fileID string) (*mm_model.FileInfo, error)
|
||||
|
||||
// Cluster service
|
||||
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
|
||||
|
||||
// Logger service
|
||||
GetLogger() mlog.LoggerIFace
|
||||
|
||||
// KVStore service
|
||||
KVSetWithOptions(key string, value []byte, options mm_model.PluginKVSetOptions) (bool, error)
|
||||
|
||||
// Store service
|
||||
GetMasterDB() (*sql.DB, error)
|
||||
|
||||
// System service
|
||||
GetDiagnosticID() string
|
||||
}
|
@ -3,29 +3,26 @@ package server
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
"github.com/mattermost/focalboard/server/services/config"
|
||||
"github.com/mattermost/focalboard/server/services/notify"
|
||||
"github.com/mattermost/focalboard/server/services/permissions"
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
"github.com/mattermost/focalboard/server/ws"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/plugin"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
|
||||
pluginapi "github.com/mattermost/mattermost-plugin-api"
|
||||
)
|
||||
|
||||
type Params struct {
|
||||
Cfg *config.Configuration
|
||||
SingleUserToken string
|
||||
DBStore store.Store
|
||||
Logger *mlog.Logger
|
||||
Logger mlog.LoggerIFace
|
||||
ServerID string
|
||||
WSAdapter ws.Adapter
|
||||
NotifyBackends []notify.Backend
|
||||
PermissionsService permissions.PermissionsService
|
||||
PluginAPI plugin.API
|
||||
Client *pluginapi.Client
|
||||
ServicesAPI model.ServicesAPI
|
||||
IsPlugin bool
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ type Server struct {
|
||||
store store.Store
|
||||
filesBackend filestore.FileBackend
|
||||
telemetry *telemetry.Service
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
cleanUpSessionsTask *scheduler.ScheduledTask
|
||||
metricsServer *metrics.Service
|
||||
metricsService *metrics.Metrics
|
||||
@ -137,7 +137,7 @@ func New(params Params) (*Server, error) {
|
||||
Notifications: notificationService,
|
||||
Logger: params.Logger,
|
||||
Permissions: params.PermissionsService,
|
||||
PluginAPI: params.PluginAPI,
|
||||
ServicesAPI: params.ServicesAPI,
|
||||
SkipTemplateInit: utils.IsRunningUnitTests(),
|
||||
}
|
||||
app := app.New(params.Cfg, wsAdapter, appServices)
|
||||
@ -207,7 +207,7 @@ func New(params Params) (*Server, error) {
|
||||
return &server, nil
|
||||
}
|
||||
|
||||
func NewStore(config *config.Configuration, isSingleUser bool, logger *mlog.Logger) (store.Store, error) {
|
||||
func NewStore(config *config.Configuration, isSingleUser bool, logger mlog.LoggerIFace) (store.Store, error) {
|
||||
sqlDB, err := sql.Open(config.DBType, config.DBConfigString)
|
||||
if err != nil {
|
||||
logger.Error("connectDatabase failed", mlog.Err(err))
|
||||
@ -350,7 +350,7 @@ func (s *Server) Config() *config.Configuration {
|
||||
return s.config
|
||||
}
|
||||
|
||||
func (s *Server) Logger() *mlog.Logger {
|
||||
func (s *Server) Logger() mlog.LoggerIFace {
|
||||
return s.logger
|
||||
}
|
||||
|
||||
@ -418,7 +418,7 @@ type telemetryOptions struct {
|
||||
cfg *config.Configuration
|
||||
telemetryID string
|
||||
serverID string
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
singleUser bool
|
||||
}
|
||||
|
||||
@ -494,7 +494,7 @@ func initTelemetry(opts telemetryOptions) *telemetry.Service {
|
||||
return telemetryService
|
||||
}
|
||||
|
||||
func initNotificationService(backends []notify.Backend, logger *mlog.Logger) (*notify.Service, error) {
|
||||
func initNotificationService(backends []notify.Backend, logger mlog.LoggerIFace) (*notify.Service, error) {
|
||||
loggerBackend := notifylogger.New(logger, mlog.LvlDebug)
|
||||
|
||||
backends = append(backends, loggerBackend)
|
||||
|
@ -15,7 +15,7 @@ type Service struct {
|
||||
}
|
||||
|
||||
// NewMetricsServer factory method to create a new prometheus server.
|
||||
func NewMetricsServer(address string, metricsService *Metrics, logger *mlog.Logger) *Service {
|
||||
func NewMetricsServer(address string, metricsService *Metrics, logger mlog.LoggerIFace) *Service {
|
||||
return &Service{
|
||||
&http.Server{
|
||||
Addr: address,
|
||||
|
@ -14,11 +14,11 @@ const (
|
||||
)
|
||||
|
||||
type Backend struct {
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
level mlog.Level
|
||||
}
|
||||
|
||||
func New(logger *mlog.Logger, level mlog.Level) *Backend {
|
||||
func New(logger mlog.LoggerIFace, level mlog.Level) *Backend {
|
||||
return &Backend{
|
||||
logger: logger,
|
||||
level: level,
|
||||
|
@ -32,7 +32,7 @@ type BackendParams struct {
|
||||
AppAPI AppAPI
|
||||
Permissions permissions.PermissionsService
|
||||
Delivery MentionDelivery
|
||||
Logger *mlog.Logger
|
||||
Logger mlog.LoggerIFace
|
||||
}
|
||||
|
||||
// Backend provides the notification backend for @mentions.
|
||||
@ -40,7 +40,7 @@ type Backend struct {
|
||||
appAPI AppAPI
|
||||
permissions permissions.PermissionsService
|
||||
delivery MentionDelivery
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
|
||||
mux sync.RWMutex
|
||||
listeners []MentionListener
|
||||
@ -150,7 +150,7 @@ func (b *Backend) BlockChanged(evt notify.BlockChangeEvent) error {
|
||||
return merr.ErrorOrNil()
|
||||
}
|
||||
|
||||
func safeCallListener(listener MentionListener, userID string, evt notify.BlockChangeEvent, logger *mlog.Logger) {
|
||||
func safeCallListener(listener MentionListener, userID string, evt notify.BlockChangeEvent, logger mlog.LoggerIFace) {
|
||||
// don't let panicky listeners stop notifications
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
|
@ -52,7 +52,7 @@ type diffGenerator struct {
|
||||
store AppAPI
|
||||
hint *model.NotificationHint
|
||||
lastNotifyAt int64
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
}
|
||||
|
||||
func (dg *diffGenerator) generateDiffs() ([]*Diff, error) {
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
func generateMarkdownDiff(oldText string, newText string, logger *mlog.Logger) string {
|
||||
func generateMarkdownDiff(oldText string, newText string, logger mlog.LoggerIFace) string {
|
||||
oldTxtNorm := normalizeText(oldText)
|
||||
newTxtNorm := normalizeText(newText)
|
||||
|
||||
|
@ -36,7 +36,7 @@ type DiffConvOpts struct {
|
||||
Language string
|
||||
MakeCardLink func(block *model.Block, board *model.Board, card *model.Block) string
|
||||
MakeBoardLink func(board *model.Board) string
|
||||
Logger *mlog.Logger
|
||||
Logger mlog.LoggerIFace
|
||||
}
|
||||
|
||||
// getTemplate returns a new or cached named template based on the language specified.
|
||||
|
@ -35,7 +35,7 @@ type notifier struct {
|
||||
store AppAPI
|
||||
permissions permissions.PermissionsService
|
||||
delivery SubscriptionDelivery
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
|
||||
hints chan *model.NotificationHint
|
||||
|
||||
|
@ -24,7 +24,7 @@ type BackendParams struct {
|
||||
AppAPI AppAPI
|
||||
Permissions permissions.PermissionsService
|
||||
Delivery SubscriptionDelivery
|
||||
Logger *mlog.Logger
|
||||
Logger mlog.LoggerIFace
|
||||
NotifyFreqCardSeconds int
|
||||
NotifyFreqBoardSeconds int
|
||||
}
|
||||
@ -35,7 +35,7 @@ type Backend struct {
|
||||
permissions permissions.PermissionsService
|
||||
delivery SubscriptionDelivery
|
||||
notifier *notifier
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
notifyFreqCardSeconds int
|
||||
notifyFreqBoardSeconds int
|
||||
}
|
||||
|
@ -31,5 +31,10 @@ func (pd *PluginDelivery) MentionDeliver(mentionedUser *mm_model.User, extract s
|
||||
ChannelId: channel.Id,
|
||||
Message: formatMessage(author.Username, extract, evt.Card.Title, link, evt.BlockChanged, boardLink, evt.Board.Title),
|
||||
}
|
||||
return mentionedUser.Id, pd.api.CreatePost(post)
|
||||
|
||||
if _, err := pd.api.CreatePost(post); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return mentionedUser.Id, nil
|
||||
}
|
||||
|
@ -7,13 +7,13 @@ import (
|
||||
mm_model "github.com/mattermost/mattermost-server/v6/model"
|
||||
)
|
||||
|
||||
type PluginAPI interface {
|
||||
type servicesAPI interface {
|
||||
// GetDirectChannel gets a direct message channel.
|
||||
// If the channel does not exist it will create it.
|
||||
GetDirectChannel(userID1, userID2 string) (*mm_model.Channel, error)
|
||||
|
||||
// CreatePost creates a post.
|
||||
CreatePost(post *mm_model.Post) error
|
||||
CreatePost(post *mm_model.Post) (*mm_model.Post, error)
|
||||
|
||||
// GetUserByID gets a user by their ID.
|
||||
GetUserByID(userID string) (*mm_model.User, error)
|
||||
@ -39,11 +39,11 @@ type PluginAPI interface {
|
||||
type PluginDelivery struct {
|
||||
botID string
|
||||
serverRoot string
|
||||
api PluginAPI
|
||||
api servicesAPI
|
||||
}
|
||||
|
||||
// New creates a PluginDelivery instance.
|
||||
func New(botID string, serverRoot string, api PluginAPI) *PluginDelivery {
|
||||
func New(botID string, serverRoot string, api servicesAPI) *PluginDelivery {
|
||||
return &PluginDelivery{
|
||||
botID: botID,
|
||||
serverRoot: serverRoot,
|
||||
|
@ -41,7 +41,8 @@ func (pd *PluginDelivery) SubscriptionDeliverSlackAttachments(teamID string, sub
|
||||
|
||||
mm_model.ParseSlackAttachment(post, attachments)
|
||||
|
||||
return pd.api.CreatePost(post)
|
||||
_, err = pd.api.CreatePost(post)
|
||||
return err
|
||||
}
|
||||
|
||||
func (pd *PluginDelivery) getDirectChannelID(teamID string, subscriberID string, subscriberType model.SubscriberType, botID string) (string, error) {
|
||||
|
@ -45,8 +45,8 @@ var (
|
||||
)
|
||||
|
||||
func Test_userByUsername(t *testing.T) {
|
||||
pluginAPI := newPlugAPIMock(mockUsers)
|
||||
delivery := New("bot_id", "server_root", pluginAPI)
|
||||
servicesAPI := newServicesAPIMock(mockUsers)
|
||||
delivery := New("bot_id", "server_root", servicesAPI)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@ -79,17 +79,17 @@ func Test_userByUsername(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type pluginAPIMock struct {
|
||||
type servicesAPIMock struct {
|
||||
users map[string]*mm_model.User
|
||||
}
|
||||
|
||||
func newPlugAPIMock(users map[string]*mm_model.User) pluginAPIMock {
|
||||
return pluginAPIMock{
|
||||
func newServicesAPIMock(users map[string]*mm_model.User) servicesAPIMock {
|
||||
return servicesAPIMock{
|
||||
users: users,
|
||||
}
|
||||
}
|
||||
|
||||
func (m pluginAPIMock) GetUserByUsername(name string) (*mm_model.User, error) {
|
||||
func (m servicesAPIMock) GetUserByUsername(name string) (*mm_model.User, error) {
|
||||
user, ok := m.users[name]
|
||||
if !ok {
|
||||
return nil, model.NewErrNotFound(name)
|
||||
@ -97,15 +97,15 @@ func (m pluginAPIMock) GetUserByUsername(name string) (*mm_model.User, error) {
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (m pluginAPIMock) GetDirectChannel(userID1, userID2 string) (*mm_model.Channel, error) {
|
||||
func (m servicesAPIMock) GetDirectChannel(userID1, userID2 string) (*mm_model.Channel, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m pluginAPIMock) CreatePost(post *mm_model.Post) error {
|
||||
return nil
|
||||
func (m servicesAPIMock) CreatePost(post *mm_model.Post) (*mm_model.Post, error) {
|
||||
return post, nil
|
||||
}
|
||||
|
||||
func (m pluginAPIMock) GetUserByID(userID string) (*mm_model.User, error) {
|
||||
func (m servicesAPIMock) GetUserByID(userID string) (*mm_model.User, error) {
|
||||
for _, user := range m.users {
|
||||
if user.Id == userID {
|
||||
return user, nil
|
||||
@ -114,7 +114,7 @@ func (m pluginAPIMock) GetUserByID(userID string) (*mm_model.User, error) {
|
||||
return nil, model.NewErrNotFound(userID)
|
||||
}
|
||||
|
||||
func (m pluginAPIMock) GetTeamMember(teamID string, userID string) (*mm_model.TeamMember, error) {
|
||||
func (m servicesAPIMock) GetTeamMember(teamID string, userID string) (*mm_model.TeamMember, error) {
|
||||
user, err := m.GetUserByID(userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -131,15 +131,15 @@ func (m pluginAPIMock) GetTeamMember(teamID string, userID string) (*mm_model.Te
|
||||
return member, nil
|
||||
}
|
||||
|
||||
func (m pluginAPIMock) GetChannelByID(channelID string) (*mm_model.Channel, error) {
|
||||
func (m servicesAPIMock) GetChannelByID(channelID string) (*mm_model.Channel, error) {
|
||||
return nil, model.NewErrNotFound(channelID)
|
||||
}
|
||||
|
||||
func (m pluginAPIMock) GetChannelMember(channelID string, userID string) (*mm_model.ChannelMember, error) {
|
||||
func (m servicesAPIMock) GetChannelMember(channelID string, userID string) (*mm_model.ChannelMember, error) {
|
||||
return nil, model.NewErrNotFound(userID)
|
||||
}
|
||||
|
||||
func (m pluginAPIMock) CreateMember(teamID string, userID string) (*mm_model.TeamMember, error) {
|
||||
func (m servicesAPIMock) CreateMember(teamID string, userID string) (*mm_model.TeamMember, error) {
|
||||
member := &mm_model.TeamMember{
|
||||
UserId: userID,
|
||||
TeamId: teamID,
|
||||
|
@ -42,11 +42,11 @@ type Backend interface {
|
||||
type Service struct {
|
||||
mux sync.RWMutex
|
||||
backends []Backend
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
}
|
||||
|
||||
// New creates a notification service with one or more Backends capable of sending notifications.
|
||||
func New(logger *mlog.Logger, backends ...Backend) (*Service, error) {
|
||||
func New(logger mlog.LoggerIFace, backends ...Backend) (*Service, error) {
|
||||
notify := &Service{
|
||||
backends: make([]Backend, 0, len(backends)),
|
||||
logger: logger,
|
||||
|
@ -13,10 +13,10 @@ import (
|
||||
|
||||
type Service struct {
|
||||
store permissions.Store
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
}
|
||||
|
||||
func New(store permissions.Store, logger *mlog.Logger) *Service {
|
||||
func New(store permissions.Store, logger mlog.LoggerIFace) *Service {
|
||||
return &Service{
|
||||
store: store,
|
||||
logger: logger,
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
permissionsMocks "github.com/mattermost/focalboard/server/services/permissions/mocks"
|
||||
|
||||
mmModel "github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -34,7 +35,7 @@ func SetupTestHelper(t *testing.T) *TestHelper {
|
||||
ctrl: ctrl,
|
||||
store: mockStore,
|
||||
api: mockAPI,
|
||||
permissions: New(mockStore, mockAPI),
|
||||
permissions: New(mockStore, mockAPI, mlog.CreateConsoleTestLogger(true, mlog.LvlError)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,20 +8,21 @@ import (
|
||||
"github.com/mattermost/focalboard/server/services/permissions"
|
||||
|
||||
mmModel "github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
type APIInterface interface {
|
||||
HasPermissionToTeam(userID string, teamID string, permission *mmModel.Permission) bool
|
||||
HasPermissionToChannel(userID string, channelID string, permission *mmModel.Permission) bool
|
||||
LogError(string, ...interface{})
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
store permissions.Store
|
||||
api APIInterface
|
||||
store permissions.Store
|
||||
api APIInterface
|
||||
logger mlog.LoggerIFace
|
||||
}
|
||||
|
||||
func New(store permissions.Store, api APIInterface) *Service {
|
||||
func New(store permissions.Store, api APIInterface, logger mlog.LoggerIFace) *Service {
|
||||
return &Service{
|
||||
store: store,
|
||||
api: api,
|
||||
@ -59,10 +60,10 @@ func (s *Service) HasPermissionToBoard(userID, boardID string, permission *mmMod
|
||||
}
|
||||
board = boards[0]
|
||||
} else if err != nil {
|
||||
s.api.LogError("error getting board",
|
||||
"boardID", boardID,
|
||||
"userID", userID,
|
||||
"error", err,
|
||||
s.logger.Error("error getting board",
|
||||
mlog.String("boardID", boardID),
|
||||
mlog.String("userID", userID),
|
||||
mlog.Err(err),
|
||||
)
|
||||
return false
|
||||
}
|
||||
@ -78,10 +79,10 @@ func (s *Service) HasPermissionToBoard(userID, boardID string, permission *mmMod
|
||||
return false
|
||||
}
|
||||
if err != nil {
|
||||
s.api.LogError("error getting member for board",
|
||||
"boardID", boardID,
|
||||
"userID", userID,
|
||||
"error", err,
|
||||
s.logger.Error("error getting member for board",
|
||||
mlog.String("boardID", boardID),
|
||||
mlog.String("userID", userID),
|
||||
mlog.Err(err),
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
@ -3,13 +3,11 @@ package mattermostauthlayer
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
pluginapi "github.com/mattermost/mattermost-plugin-api"
|
||||
|
||||
mmModel "github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/plugin"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
|
||||
@ -25,35 +23,43 @@ var systemsBot = &mmModel.Bot{
|
||||
DisplayName: "System",
|
||||
}
|
||||
|
||||
// servicesAPI is the interface required my the MattermostAuthLayer to interact with
|
||||
// the mattermost-server. You can use plugin-api or product-api adapter implementations.
|
||||
type servicesAPI interface {
|
||||
GetDirectChannel(userID1, userID2 string) (*mmModel.Channel, error)
|
||||
GetChannelByID(channelID string) (*mmModel.Channel, error)
|
||||
GetChannelMember(channelID string, userID string) (*mmModel.ChannelMember, error)
|
||||
GetChannelsForTeamForUser(teamID string, userID string, includeDeleted bool) (mmModel.ChannelList, error)
|
||||
GetUserByID(userID string) (*mmModel.User, error)
|
||||
UpdateUser(user *mmModel.User) (*mmModel.User, error)
|
||||
GetUserByEmail(email string) (*mmModel.User, error)
|
||||
GetUserByUsername(username string) (*mmModel.User, error)
|
||||
GetLicense() *mmModel.License
|
||||
GetFileInfo(fileID string) (*mmModel.FileInfo, error)
|
||||
GetCloudLimits() (*mmModel.ProductLimits, error)
|
||||
EnsureBot(bot *mmModel.Bot) (string, error)
|
||||
CreatePost(post *mmModel.Post) (*mmModel.Post, error)
|
||||
}
|
||||
|
||||
// Store represents the abstraction of the data storage.
|
||||
type MattermostAuthLayer struct {
|
||||
store.Store
|
||||
dbType string
|
||||
mmDB *sql.DB
|
||||
logger *mlog.Logger
|
||||
pluginAPI plugin.API
|
||||
logger mlog.LoggerIFace
|
||||
servicesAPI servicesAPI
|
||||
tablePrefix string
|
||||
client *pluginapi.Client
|
||||
}
|
||||
|
||||
// New creates a new SQL implementation of the store.
|
||||
func New(
|
||||
dbType string,
|
||||
db *sql.DB,
|
||||
store store.Store,
|
||||
logger *mlog.Logger,
|
||||
pluginAPI plugin.API,
|
||||
tablePrefix string,
|
||||
client *pluginapi.Client,
|
||||
) (*MattermostAuthLayer, error) {
|
||||
func New(dbType string, db *sql.DB, store store.Store, logger mlog.LoggerIFace, api servicesAPI, tablePrefix string) (*MattermostAuthLayer, error) {
|
||||
layer := &MattermostAuthLayer{
|
||||
Store: store,
|
||||
dbType: dbType,
|
||||
mmDB: db,
|
||||
logger: logger,
|
||||
pluginAPI: pluginAPI,
|
||||
servicesAPI: api,
|
||||
tablePrefix: tablePrefix,
|
||||
client: client,
|
||||
}
|
||||
|
||||
return layer, nil
|
||||
@ -82,7 +88,7 @@ func (s *MattermostAuthLayer) GetRegisteredUserCount() (int, error) {
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) GetUserByID(userID string) (*model.User, error) {
|
||||
mmuser, err := s.pluginAPI.GetUser(userID)
|
||||
mmuser, err := s.servicesAPI.GetUserByID(userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -91,7 +97,7 @@ func (s *MattermostAuthLayer) GetUserByID(userID string) (*model.User, error) {
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) GetUserByEmail(email string) (*model.User, error) {
|
||||
mmuser, err := s.pluginAPI.GetUserByEmail(email)
|
||||
mmuser, err := s.servicesAPI.GetUserByEmail(email)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -100,7 +106,7 @@ func (s *MattermostAuthLayer) GetUserByEmail(email string) (*model.User, error)
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) GetUserByUsername(username string) (*model.User, error) {
|
||||
mmuser, err := s.pluginAPI.GetUserByUsername(username)
|
||||
mmuser, err := s.servicesAPI.GetUserByUsername(username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -125,7 +131,7 @@ func (s *MattermostAuthLayer) UpdateUserPasswordByID(userID, password string) er
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) PatchUserProps(userID string, patch model.UserPropPatch) error {
|
||||
user, err := s.pluginAPI.GetUser(userID)
|
||||
user, err := s.servicesAPI.GetUserByID(userID)
|
||||
if err != nil {
|
||||
s.logger.Error("failed to fetch user", mlog.String("userID", userID), mlog.Err(err))
|
||||
return err
|
||||
@ -143,7 +149,7 @@ func (s *MattermostAuthLayer) PatchUserProps(userID string, patch model.UserProp
|
||||
|
||||
user.Props = props
|
||||
|
||||
if _, err := s.pluginAPI.UpdateUser(user); err != nil {
|
||||
if _, err := s.servicesAPI.UpdateUser(user); err != nil {
|
||||
s.logger.Error("failed to update user", mlog.String("userID", userID), mlog.Err(err))
|
||||
return err
|
||||
}
|
||||
@ -366,7 +372,7 @@ func (s *MattermostAuthLayer) CloseRows(rows *sql.Rows) {
|
||||
func (s *MattermostAuthLayer) CreatePrivateWorkspace(userID string) (string, error) {
|
||||
// we emulate a private workspace by creating
|
||||
// a DM channel from the user to themselves.
|
||||
channel, err := s.pluginAPI.GetDirectChannel(userID, userID)
|
||||
channel, err := s.servicesAPI.GetDirectChannel(userID, userID)
|
||||
if err != nil {
|
||||
s.logger.Error("error fetching private workspace", mlog.String("userID", userID), mlog.Err(err))
|
||||
return "", err
|
||||
@ -406,17 +412,23 @@ func mmUserToFbUser(mmUser *mmModel.User) model.User {
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) GetFileInfo(id string) (*mmModel.FileInfo, error) {
|
||||
fileInfo, appErr := s.pluginAPI.GetFileInfo(id)
|
||||
if appErr != nil {
|
||||
fileInfo, err := s.servicesAPI.GetFileInfo(id)
|
||||
if err != nil {
|
||||
// Not finding fileinfo is fine because we don't have data for
|
||||
// any existing files already uploaded in Boards before this code
|
||||
// was deployed.
|
||||
if appErr.StatusCode == http.StatusNotFound {
|
||||
return nil, nil
|
||||
var appErr *mmModel.AppError
|
||||
if errors.As(err, &appErr) {
|
||||
if appErr.StatusCode == http.StatusNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
s.logger.Error("error fetching fileinfo", mlog.String("id", id), mlog.Err(appErr))
|
||||
return nil, appErr
|
||||
s.logger.Error("error fetching fileinfo",
|
||||
mlog.String("id", id),
|
||||
mlog.Err(err),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return fileInfo, nil
|
||||
@ -484,7 +496,7 @@ func (s *MattermostAuthLayer) SaveFileInfo(fileInfo *mmModel.FileInfo) error {
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) GetLicense() *mmModel.License {
|
||||
return s.pluginAPI.GetLicense()
|
||||
return s.servicesAPI.GetLicense()
|
||||
}
|
||||
|
||||
func boardFields(prefix string) []string {
|
||||
@ -621,7 +633,7 @@ func (s *MattermostAuthLayer) boardsFromRows(rows *sql.Rows) ([]*model.Board, er
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) GetCloudLimits() (*mmModel.ProductLimits, error) {
|
||||
return s.pluginAPI.GetCloudLimits()
|
||||
return s.servicesAPI.GetCloudLimits()
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) implicitBoardMembershipsFromRows(rows *sql.Rows) ([]*model.BoardMember, error) {
|
||||
@ -646,6 +658,7 @@ func (s *MattermostAuthLayer) implicitBoardMembershipsFromRows(rows *sql.Rows) (
|
||||
|
||||
return boardMembers, nil
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) GetMemberForBoard(boardID, userID string) (*model.BoardMember, error) {
|
||||
bm, err := s.Store.GetMemberForBoard(boardID, userID)
|
||||
if model.IsErrNotFound(err) {
|
||||
@ -654,7 +667,7 @@ func (s *MattermostAuthLayer) GetMemberForBoard(boardID, userID string) (*model.
|
||||
return nil, err
|
||||
}
|
||||
if b.ChannelID != "" {
|
||||
_, err := s.pluginAPI.GetChannelMember(b.ChannelID, userID)
|
||||
_, err := s.servicesAPI.GetChannelMember(b.ChannelID, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -772,7 +785,7 @@ func (s *MattermostAuthLayer) GetBoardsForUserAndTeam(userID, teamID string) ([]
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) SearchUserChannels(teamID, userID, query string) ([]*mmModel.Channel, error) {
|
||||
channels, err := s.pluginAPI.GetChannelsForTeamForUser(teamID, userID, false)
|
||||
channels, err := s.servicesAPI.GetChannelsForTeamForUser(teamID, userID, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -794,7 +807,7 @@ func (s *MattermostAuthLayer) SearchUserChannels(teamID, userID, query string) (
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) GetChannel(teamID, channelID string) (*mmModel.Channel, error) {
|
||||
channel, err := s.pluginAPI.GetChannel(channelID)
|
||||
channel, err := s.servicesAPI.GetChannelByID(channelID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -802,7 +815,7 @@ func (s *MattermostAuthLayer) GetChannel(teamID, channelID string) (*mmModel.Cha
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) getSystemBotID() (string, error) {
|
||||
botID, err := s.client.Bot.EnsureBot(systemsBot)
|
||||
botID, err := s.servicesAPI.EnsureBot(systemsBot)
|
||||
if err != nil {
|
||||
s.logger.Error("failed to ensure system bot", mlog.String("username", systemsBot.Username), mlog.Err(err))
|
||||
return "", err
|
||||
@ -818,7 +831,7 @@ func (s *MattermostAuthLayer) SendMessage(message, postType string, receipts []s
|
||||
}
|
||||
|
||||
for _, receipt := range receipts {
|
||||
channel, err := s.pluginAPI.GetDirectChannel(botID, receipt)
|
||||
channel, err := s.servicesAPI.GetDirectChannel(botID, receipt)
|
||||
if err != nil {
|
||||
s.logger.Error(
|
||||
"failed to get DM channel between system bot and user for receipt",
|
||||
@ -836,7 +849,7 @@ func (s *MattermostAuthLayer) SendMessage(message, postType string, receipts []s
|
||||
Type: postType,
|
||||
}
|
||||
|
||||
if _, err := s.pluginAPI.CreatePost(post); err != nil {
|
||||
if _, err := s.servicesAPI.CreatePost(post); err != nil {
|
||||
s.logger.Error(
|
||||
"failed to send message to receipt from SendMessage",
|
||||
mlog.String("receipt", receipt),
|
||||
|
@ -420,15 +420,23 @@ func (s *SQLStore) getBestTeamForBoard(tx sq.BaseRunner, board *model.Board) (st
|
||||
// no common teams found. Let's try finding the best suitable team
|
||||
if board.Type == "D" {
|
||||
// get DM's creator and pick one of their team
|
||||
channel, appErr := (*s.pluginAPI).GetChannel(board.ChannelID)
|
||||
if appErr != nil {
|
||||
s.logger.Error("failed to fetch DM channel for board", mlog.String("board_id", board.ID), mlog.String("channel_id", board.ChannelID), mlog.Err(appErr))
|
||||
return "", appErr
|
||||
channel, err := (s.servicesAPI).GetChannelByID(board.ChannelID)
|
||||
if err != nil {
|
||||
s.logger.Error("failed to fetch DM channel for board",
|
||||
mlog.String("board_id", board.ID),
|
||||
mlog.String("channel_id", board.ChannelID),
|
||||
mlog.Err(err),
|
||||
)
|
||||
return "", err
|
||||
}
|
||||
|
||||
if _, ok := userTeams[channel.CreatorId]; !ok {
|
||||
s.logger.Error("channel creator not found in user teams",
|
||||
mlog.String("board_id", board.ID),
|
||||
mlog.String("channel_id", board.ChannelID),
|
||||
mlog.String("creator_id", channel.CreatorId),
|
||||
)
|
||||
err := fmt.Errorf("%w board_id: %s, channel_id: %s, creator_id: %s", errChannelCreatorNotInTeam, board.ID, board.ChannelID, channel.CreatorId)
|
||||
s.logger.Error(err.Error())
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
@ -4,21 +4,27 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/plugin"
|
||||
mmModel "github.com/mattermost/mattermost-server/v6/model"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
// servicesAPI is the interface required my the Params to interact with the mattermost-server.
|
||||
// You can use plugin-api or product-api adapter implementations.
|
||||
type servicesAPI interface {
|
||||
GetChannelByID(string) (*mmModel.Channel, error)
|
||||
}
|
||||
|
||||
type Params struct {
|
||||
DBType string
|
||||
ConnectionString string
|
||||
TablePrefix string
|
||||
Logger *mlog.Logger
|
||||
Logger mlog.LoggerIFace
|
||||
DB *sql.DB
|
||||
IsPlugin bool
|
||||
IsSingleUser bool
|
||||
NewMutexFn MutexFactory
|
||||
PluginAPI *plugin.API
|
||||
ServicesAPI servicesAPI
|
||||
}
|
||||
|
||||
func (p Params) CheckValid() error {
|
||||
|
@ -4,8 +4,6 @@ import (
|
||||
"database/sql"
|
||||
"net/url"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/plugin"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
@ -24,9 +22,9 @@ type SQLStore struct {
|
||||
connectionString string
|
||||
isPlugin bool
|
||||
isSingleUser bool
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
NewMutexFn MutexFactory
|
||||
pluginAPI *plugin.API
|
||||
servicesAPI servicesAPI
|
||||
isBinaryParam bool
|
||||
}
|
||||
|
||||
@ -51,7 +49,7 @@ func New(params Params) (*SQLStore, error) {
|
||||
isPlugin: params.IsPlugin,
|
||||
isSingleUser: params.IsSingleUser,
|
||||
NewMutexFn: params.NewMutexFn,
|
||||
pluginAPI: params.PluginAPI,
|
||||
servicesAPI: params.ServicesAPI,
|
||||
}
|
||||
|
||||
var err error
|
||||
|
@ -27,7 +27,7 @@ type Tracker map[string]interface{}
|
||||
|
||||
type Service struct {
|
||||
trackers map[string]TrackerFunc
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
rudderClient rudder.Client
|
||||
telemetryID string
|
||||
timestampLastTelemetrySent time.Time
|
||||
@ -38,7 +38,7 @@ type RudderConfig struct {
|
||||
DataplaneURL string
|
||||
}
|
||||
|
||||
func New(telemetryID string, logger *mlog.Logger) *Service {
|
||||
func New(telemetryID string, logger mlog.LoggerIFace) *Service {
|
||||
service := &Service{
|
||||
logger: logger,
|
||||
telemetryID: telemetryID,
|
||||
|
@ -34,11 +34,11 @@ func (wh *Client) NotifyUpdate(block model.Block) {
|
||||
// Client is a webhook client.
|
||||
type Client struct {
|
||||
config *config.Configuration
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
}
|
||||
|
||||
// NewClient creates a new Client.
|
||||
func NewClient(config *config.Configuration, logger *mlog.Logger) *Client {
|
||||
func NewClient(config *config.Configuration, logger mlog.LoggerIFace) *Client {
|
||||
return &Client{
|
||||
config: config,
|
||||
logger: logger,
|
||||
|
@ -26,11 +26,11 @@ type CallbackQueue struct {
|
||||
|
||||
idone uint32
|
||||
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
}
|
||||
|
||||
// NewCallbackQueue creates a new CallbackQueue and starts a thread pool to service it.
|
||||
func NewCallbackQueue(name string, queueSize int, poolSize int, logger *mlog.Logger) *CallbackQueue {
|
||||
func NewCallbackQueue(name string, queueSize int, poolSize int, logger mlog.LoggerIFace) *CallbackQueue {
|
||||
cn := &CallbackQueue{
|
||||
name: name,
|
||||
poolSize: poolSize,
|
||||
|
@ -32,11 +32,11 @@ type Server struct {
|
||||
basePrefix string
|
||||
port int
|
||||
ssl bool
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
}
|
||||
|
||||
// NewServer creates a new instance of the webserver.
|
||||
func NewServer(rootPath string, serverRoot string, port int, ssl, localOnly bool, logger *mlog.Logger) *Server {
|
||||
func NewServer(rootPath string, serverRoot string, port int, ssl, localOnly bool, logger mlog.LoggerIFace) *Server {
|
||||
r := mux.NewRouter()
|
||||
|
||||
basePrefix := os.Getenv("FOCALBOARD_HTTP_SERVER_BASEPATH")
|
||||
|
@ -3,8 +3,9 @@ package web
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
func Test_NewServer(t *testing.T) {
|
||||
@ -15,7 +16,7 @@ func Test_NewServer(t *testing.T) {
|
||||
ssl bool
|
||||
port int
|
||||
localOnly bool
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
expectedBaseURL string
|
||||
expectedServerAddr string
|
||||
}{
|
||||
|
@ -13,7 +13,6 @@ import (
|
||||
"github.com/mattermost/focalboard/server/utils"
|
||||
|
||||
mmModel "github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/plugin"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
@ -35,11 +34,11 @@ type PluginAdapterInterface interface {
|
||||
}
|
||||
|
||||
type PluginAdapter struct {
|
||||
api plugin.API
|
||||
api servicesAPI
|
||||
auth auth.AuthInterface
|
||||
staleThreshold time.Duration
|
||||
store Store
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
|
||||
listenersMU sync.RWMutex
|
||||
listeners map[string]*PluginAdapterClient
|
||||
@ -50,7 +49,14 @@ type PluginAdapter struct {
|
||||
listenersByBlock map[string][]*PluginAdapterClient
|
||||
}
|
||||
|
||||
func NewPluginAdapter(api plugin.API, auth auth.AuthInterface, store Store, logger *mlog.Logger) *PluginAdapter {
|
||||
// servicesAPI is the interface required by the PluginAdapter to interact with
|
||||
// the mattermost-server.
|
||||
type servicesAPI interface {
|
||||
PublishWebSocketEvent(event string, payload map[string]interface{}, broadcast *mmModel.WebsocketBroadcast)
|
||||
PublishPluginClusterEvent(ev mmModel.PluginClusterEvent, opts mmModel.PluginClusterEventSendOptions) error
|
||||
}
|
||||
|
||||
func NewPluginAdapter(api servicesAPI, auth auth.AuthInterface, store Store, logger mlog.LoggerIFace) *PluginAdapter {
|
||||
return &PluginAdapter{
|
||||
api: api,
|
||||
auth: auth,
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
mmModel "github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
type ClusterMessage struct {
|
||||
@ -16,9 +17,9 @@ type ClusterMessage struct {
|
||||
func (pa *PluginAdapter) sendMessageToCluster(id string, clusterMessage *ClusterMessage) {
|
||||
b, err := json.Marshal(clusterMessage)
|
||||
if err != nil {
|
||||
pa.api.LogError("couldn't get JSON bytes from cluster message",
|
||||
"id", id,
|
||||
"err", err,
|
||||
pa.logger.Error("couldn't get JSON bytes from cluster message",
|
||||
mlog.String("id", id),
|
||||
mlog.Err(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@ -29,21 +30,21 @@ func (pa *PluginAdapter) sendMessageToCluster(id string, clusterMessage *Cluster
|
||||
}
|
||||
|
||||
if err := pa.api.PublishPluginClusterEvent(event, opts); err != nil {
|
||||
pa.api.LogError("error publishing cluster event",
|
||||
"id", id,
|
||||
"err", err,
|
||||
pa.logger.Error("error publishing cluster event",
|
||||
mlog.String("id", id),
|
||||
mlog.Err(err),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (pa *PluginAdapter) HandleClusterEvent(ev mmModel.PluginClusterEvent) {
|
||||
pa.api.LogDebug("received cluster event", "id", ev.Id)
|
||||
pa.logger.Debug("received cluster event", mlog.String("id", ev.Id))
|
||||
|
||||
var clusterMessage ClusterMessage
|
||||
if err := json.Unmarshal(ev.Data, &clusterMessage); err != nil {
|
||||
pa.api.LogError("cannot unmarshal cluster message data",
|
||||
"id", ev.Id,
|
||||
"err", err,
|
||||
pa.logger.Error("cannot unmarshal cluster message data",
|
||||
mlog.String("id", ev.Id),
|
||||
mlog.Err(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@ -61,9 +62,9 @@ func (pa *PluginAdapter) HandleClusterEvent(ev mmModel.PluginClusterEvent) {
|
||||
}
|
||||
if action == "" {
|
||||
// no action was specified in the event; assume block change and warn.
|
||||
pa.api.LogWarn("cannot determine action from cluster message data",
|
||||
"id", ev.Id,
|
||||
"payload", clusterMessage.Payload,
|
||||
pa.logger.Warn("cannot determine action from cluster message data",
|
||||
mlog.String("id", ev.Id),
|
||||
mlog.Map("payload", clusterMessage.Payload),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ type Server struct {
|
||||
auth *auth.Auth
|
||||
singleUserToken string
|
||||
isMattermostAuth bool
|
||||
logger *mlog.Logger
|
||||
logger mlog.LoggerIFace
|
||||
store Store
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ func (wss *websocketSession) isAuthenticated() bool {
|
||||
}
|
||||
|
||||
// NewServer creates a new Server.
|
||||
func NewServer(auth *auth.Auth, singleUserToken string, isMattermostAuth bool, logger *mlog.Logger, store Store) *Server {
|
||||
func NewServer(auth *auth.Auth, singleUserToken string, isMattermostAuth bool, logger mlog.LoggerIFace, store Store) *Server {
|
||||
return &Server{
|
||||
listeners: make(map[*websocketSession]bool),
|
||||
listenersByTeam: make(map[string][]*websocketSession),
|
||||
|
Loading…
Reference in New Issue
Block a user