You've already forked focalboard
							
							
				mirror of
				https://github.com/mattermost/focalboard.git
				synced 2025-10-31 00:17:42 +02:00 
			
		
		
		
	Multi product architecture (#3381)
- provides support for compiling Boards directly into the Mattermost suite server - a ServicesAPI interface replaces the PluginAPI to allow for implementations coming from pluginAPI and suite server. - a new product package provides a place to register Boards as a suite product and handles life-cycle events - a new boards package replaces much of the mattermost-plugin logic, allowing this to be shared between plugin and product - Boards now uses module workspaces; run make setup-go-work
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							3d753a15e5
						
					
				
				
					commit
					4b0fb92fba
				
			
							
								
								
									
										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,16 +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) | ||||
| 	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 { | ||||
| @@ -66,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) | ||||
| 	}) | ||||
| @@ -89,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) | ||||
| 	}) | ||||
| @@ -103,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) | ||||
| 	}) | ||||
| @@ -118,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), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user