From 1ff05f76c0edfa6f066d8c3eaa27983c52068f5c Mon Sep 17 00:00:00 2001 From: Ben Schumacher Date: Tue, 1 Oct 2024 11:26:44 +0200 Subject: [PATCH 01/10] [MM-57194] Mark confidential settings as secrets (#1118) --- go.mod | 54 +++++++++++++------------ go.sum | 113 +++++++++++++++++++++++----------------------------- plugin.json | 3 +- 3 files changed, 81 insertions(+), 89 deletions(-) diff --git a/go.mod b/go.mod index 30f8bc05b..9bc47d00f 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/mattermost/mattermost-plugin-jira -go 1.21.8 +go 1.22 + +toolchain go1.22.2 require ( github.com/andygrunwald/go-jira v1.16.0 @@ -10,31 +12,34 @@ require ( github.com/gorilla/mux v1.8.1 github.com/jarcoal/httpmock v1.0.8 github.com/mattermost/mattermost-plugin-autolink v1.2.2-0.20210709183311-c8fa30db649f - github.com/mattermost/mattermost/server/public v0.0.17-0.20240313200153-4d7437d30e1c + github.com/mattermost/mattermost/server/public v0.1.7 github.com/pkg/errors v0.9.1 github.com/rbriski/atlassian-jwt v0.0.0-20240408161306-6b6d681cf2d9 github.com/rudderlabs/analytics-go v3.3.3+incompatible - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 github.com/trivago/tgo v1.0.7 - golang.org/x/oauth2 v0.17.0 - golang.org/x/text v0.14.0 + golang.org/x/oauth2 v0.21.0 + golang.org/x/text v0.16.0 ) require ( - github.com/davecgh/go-spew v1.1.1 // indirect + filippo.io/edwards25519 v1.1.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fatih/structs v1.1.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect - github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect - github.com/go-sql-driver/mysql v1.7.1 // indirect + github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/golang-jwt/jwt/v4 v4.4.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.5.1 // indirect - github.com/hashicorp/go-hclog v1.6.2 // indirect - github.com/hashicorp/go-plugin v1.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-plugin v1.6.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/klauspost/compress v1.15.14 // indirect github.com/klauspost/cpuid/v2 v2.2.3 // indirect @@ -49,29 +54,28 @@ require ( github.com/oklog/run v1.1.0 // indirect github.com/pborman/uuid v1.2.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/philhofer/fwd v1.1.2 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - github.com/segmentio/backo-go v1.0.1 // indirect + github.com/segmentio/backo-go v1.1.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/stretchr/objx v0.5.1 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/tidwall/gjson v1.17.1 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect - github.com/tinylib/msgp v1.1.9 // indirect + github.com/tinylib/msgp v1.2.0 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/wiggin77/merror v1.0.5 // indirect github.com/wiggin77/srslog v1.0.1 // indirect github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect go.uber.org/atomic v1.9.0 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.18.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/grpc v1.62.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade // indirect + google.golang.org/grpc v1.65.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index d283ffd7d..bdc0baeb7 100644 --- a/go.sum +++ b/go.sum @@ -43,6 +43,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= @@ -138,7 +140,6 @@ github.com/blevesearch/zap/v12 v12.0.14/go.mod h1:rOnuZOiMKPQj18AEKEHJxuI14236tT github.com/blevesearch/zap/v13 v13.0.6/go.mod h1:L89gsjdRKGyGrRN6nCpIScCvvkyxvmeDCwZRcjjPCrw= github.com/blevesearch/zap/v14 v14.0.5/go.mod h1:bWe8S7tRrSBTIaZ6cLRbgNH4TUDaC9LZSpRGs85AsGY= github.com/blevesearch/zap/v15 v15.0.3/go.mod h1:iuwQrImsh1WjWJ0Ue2kBqY83a0rFtJTqfa9fp1rbVVU= -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/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= @@ -195,8 +196,9 @@ github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= github.com/cznic/strutil v0.0.0-20181122101858-275e90344537/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.0.0-20200620013148-b91950f658ec/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dghubble/oauth1 v0.5.0 h1:uJqX7Rzr3QRmp2slUWqI9Sm8NoP65AMiyXiijOWWLvQ= github.com/dghubble/oauth1 v0.5.0/go.mod h1:8V8BMV9DJRREZx/lUaHtrs7GUMXpzbMqJxINCasxYug= @@ -243,8 +245,8 @@ github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= @@ -271,8 +273,8 @@ github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/go-asn1-ber/asn1-ber v1.3.2-0.20191121212151-29be175fc3a3/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-asn1-ber/asn1-ber v1.5.3/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= -github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA= -github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-asn1-ber/asn1-ber v1.5.7 h1:DTX+lbVTWaTw1hQ+PbZPlnDZPEIs0SS/GCZAl535dDk= +github.com/go-asn1-ber/asn1-ber v1.5.7/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -293,8 +295,8 @@ github.com/go-resty/resty/v2 v2.6.0/go.mod h1:PwvJS6hvaPkjtjNg9ph+VrSD92bi5Zq73w github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= -github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= @@ -344,8 +346,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -410,8 +412,8 @@ github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlI github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= @@ -437,8 +439,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng 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 v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v1.6.2 h1:NOtoftovWkDheyUM/8JW3QMiXyxJK3uHRK7wV04nD2I= -github.com/hashicorp/go-hclog v1.6.2/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= @@ -448,8 +450,8 @@ github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-plugin v1.4.1/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= -github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= -github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= +github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI= +github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= @@ -578,8 +580,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= @@ -627,8 +629,8 @@ github.com/mattermost/mattermost-plugin-autolink v1.2.2-0.20210709183311-c8fa30d github.com/mattermost/mattermost-plugin-autolink v1.2.2-0.20210709183311-c8fa30db649f/go.mod h1:JO5RQqTYL2D1zDz7+5ucAmNeRMiudDvZQoRtqbm+1sU= github.com/mattermost/mattermost-server/v5 v5.3.2-0.20210621071817-df224571d8a1 h1:5/lZibP83SrOpuKs4fE782pfWNFX/QTWwO2PuJJwGJ4= github.com/mattermost/mattermost-server/v5 v5.3.2-0.20210621071817-df224571d8a1/go.mod h1:S3zT7H4bAxsev1d2ThoSRBhyEXZa6JZOfpxvy2B25y4= -github.com/mattermost/mattermost/server/public v0.0.17-0.20240313200153-4d7437d30e1c h1:nMP/FVExLX18NQ6orSe2kaQyMxQqDC/4ZbKEDF51UEY= -github.com/mattermost/mattermost/server/public v0.0.17-0.20240313200153-4d7437d30e1c/go.mod h1:fcIzW52CGpZhLXJyeNIMnK9rzWdOuSpbYmh3GDBECQM= +github.com/mattermost/mattermost/server/public v0.1.7 h1:WA+fnLrQQeE6xTyHERqcGiKljBFK6m8WYL4Pez07ko4= +github.com/mattermost/mattermost/server/public v0.1.7/go.mod h1:SkTKbMul91Rq0v2dIxe8mqzUOY+3KwlwwLmAlxDfGCk= github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0/go.mod h1:nV5bfVpT//+B1RPD2JvRnxbkLmJEYXmRaaVl15fsXjs= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= @@ -784,8 +786,8 @@ github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9 github.com/peterbourgon/diskv v0.0.0-20171120014656-2973218375c3/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= -github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= +github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4= +github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= @@ -797,8 +799,9 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -872,8 +875,8 @@ github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZ github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/backo-go v0.0.0-20200129164019-23eae7c10bd3/go.mod h1:9/Rh6yILuLysoQnZ2oNooD2g7aBnvM7r/fNVxRNWfBc= -github.com/segmentio/backo-go v1.0.1 h1:68RQccglxZeyURy93ASB/2kc9QudzgIDexJ927N++y4= -github.com/segmentio/backo-go v1.0.1/go.mod h1:9/Rh6yILuLysoQnZ2oNooD2g7aBnvM7r/fNVxRNWfBc= +github.com/segmentio/backo-go v1.1.0 h1:cJIfHQUdmLsd8t9IXqf5J8SdrOMn9vMa7cIvOavHAhc= +github.com/segmentio/backo-go v1.1.0/go.mod h1:ckenwdf+v/qbyhVdNPWHnqh2YdJBED1O9cidYyM5J18= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= @@ -943,10 +946,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0= -github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -954,12 +955,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/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= @@ -980,8 +978,8 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg= -github.com/tinylib/msgp v1.1.9 h1:SHf3yoO2sGA0veCJeCBYLHuttAVFHGm2RHgNodW7wQU= -github.com/tinylib/msgp v1.1.9/go.mod h1:BCXGB54lDD8qUEPmiG0cQQUANC4IUQyB2ItS2UDlO/k= +github.com/tinylib/msgp v1.2.0 h1:0uKB/662twsVBpYUPbokj4sTSKhWFKB7LopO2kWK8lY= +github.com/tinylib/msgp v1.2.0/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiYPHro= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/trivago/tgo v1.0.7 h1:uaWH/XIy9aWYWpjm2CU3RpcqZXmX2ysQ9/Go+d9gyrM= @@ -1042,7 +1040,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= @@ -1107,9 +1104,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1150,7 +1146,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -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= @@ -1207,9 +1202,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= 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= @@ -1220,8 +1214,8 @@ golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= -golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 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= @@ -1234,7 +1228,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/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= @@ -1314,14 +1307,12 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1333,9 +1324,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1405,7 +1395,6 @@ golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 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= @@ -1443,8 +1432,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -1486,8 +1473,8 @@ google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade h1:oCRSWfwGXQsqlVdErcyTt4A93Y8fo0/9D4b1gnI++qo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= @@ -1512,8 +1499,8 @@ google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= -google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= 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= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1526,8 +1513,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/plugin.json b/plugin.json index c8d184af1..7c9408ac4 100644 --- a/plugin.json +++ b/plugin.json @@ -38,7 +38,8 @@ "help_text": "The secret used to authenticate the webhook to Mattermost.", "regenerate_help_text": "Regenerates the secret for the webhook URL endpoint. Regenerating the secret invalidates your existing Jira integrations.", "placeholder": "", - "default": null + "default": null, + "secret": true }, { "key": "RolesAllowedToEditJiraSubscriptions", From 85725f33f4275efcc56cdd8a2c77dfa5c75dc18f Mon Sep 17 00:00:00 2001 From: Raghav Aggarwal Date: Fri, 18 Oct 2024 17:59:35 +0530 Subject: [PATCH 02/10] [MM-586] Added API token for fetching issue details (#1102) * [MM-586] Added API token for fetching issue details 1. Added API token field in syatem console. 2. Added logic to fetch issue details with API token for comment and issue created events. * Remove junit file * Review fixes * Review fixes * Update .gitignore file * Review fix * [MM-866] Add handling for 404 and 403 status code in response * [MM-866] Moved the logic to use API token after trying to use the token of connected user * [MM-866] Fix lint error --- plugin.json | 8 ++++++++ server/issue.go | 40 ++++++++++++++++++++++++++++++++++++++++ server/kv.go | 7 ++++++- server/plugin.go | 3 +++ server/webhook_jira.go | 11 +++++++++++ 5 files changed, 68 insertions(+), 1 deletion(-) diff --git a/plugin.json b/plugin.json index 7c9408ac4..7488278fe 100644 --- a/plugin.json +++ b/plugin.json @@ -114,6 +114,14 @@ "help_text": "Display subscription name in post when a subscription posts to a channel", "placeholder": "", "default": false + }, + { + "key": "AdminAPIToken", + "display_name": "Admin API Token", + "type": "text", + "help_text": "Set this [API token](https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/) to get notified for comment and issue created events even if the user triggering the event is not connected to Jira.\n **Note:** API token should be created using an admin Jira account. Otherwise, the notification will not be delivered for the project the user cannot access.", + "placeholder": "", + "default": "" } ] } diff --git a/server/issue.go b/server/issue.go index d5a399307..f498d5bea 100644 --- a/server/issue.go +++ b/server/issue.go @@ -6,6 +6,7 @@ package main import ( "encoding/json" "fmt" + "io" "net/http" "regexp" "strconv" @@ -1094,3 +1095,42 @@ func (p *Plugin) GetIssueByKey(instanceID, mattermostUserID types.ID, issueKey s } return issue, nil } + +func (p *Plugin) GetIssueDataWithAPIToken(issueID, instanceID string) (*jira.Issue, error) { + client := &http.Client{} + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/rest/api/2/issue/%s", instanceID, issueID), nil) + if err != nil { + return nil, errors.Wrapf(err, "failed to create http request for fetching issue data. IssueID: %s", issueID) + } + + req.Header.Set("Authorization", fmt.Sprintf("Basic %s", p.getConfig().AdminAPIToken)) + + resp, err := client.Do(req) + if err != nil { + return nil, errors.Wrapf(err, "failed to get issue data. IssueID: %s", issueID) + } + + if resp == nil || resp.Body == nil { + return nil, errors.Wrapf(err, "missing data for issue. StatusCode: %d, IssueID: %s", resp.StatusCode, issueID) + } + + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, errors.Wrapf(err, "failed to read issue data. StatusCode: %d, IssueID: %s", resp.StatusCode, issueID) + } + + if resp.StatusCode == http.StatusNotFound { + return nil, errors.Errorf("issue does not exist or user does not have permission to fetch the issue details. StatusCode: %d, IssueID: %s", resp.StatusCode, issueID) + } else if resp.StatusCode == http.StatusForbidden { + return nil, errors.Errorf("user does not have permission to fetch the issue details. StatusCode: %d, IssueID: %s", resp.StatusCode, issueID) + } + + issue := &jira.Issue{} + if err = json.Unmarshal(body, issue); err != nil { + return nil, errors.Wrapf(err, "failed to unmarshal issue data. IssueID: %s", issueID) + } + + return issue, nil +} diff --git a/server/kv.go b/server/kv.go index fbf091dc7..38357d418 100644 --- a/server/kv.go +++ b/server/kv.go @@ -180,8 +180,13 @@ func (store store) LoadMattermostUserID(instanceID types.ID, jiraUserNameOrID st err := store.get(keyWithInstanceID(instanceID, types.ID(jiraUserNameOrID)), &mattermostUserID) if err != nil { return "", errors.Wrapf(err, - "failed to load Mattermost user ID for Jira user/ID: "+jiraUserNameOrID) + "failed to load Mattermost user ID for Jira username/ID: %s", jiraUserNameOrID) } + + if mattermostUserID == "" { + return "", errors.Errorf("failed to load Mattermost user ID for Jira username/ID: %s", jiraUserNameOrID) + } + return mattermostUserID, nil } diff --git a/server/plugin.go b/server/plugin.go index 50ff0ed79..02b5c34c5 100644 --- a/server/plugin.go +++ b/server/plugin.go @@ -81,6 +81,9 @@ type externalConfig struct { // Display subscription name in notifications DisplaySubscriptionNameInNotifications bool + + // API token from Jira + AdminAPIToken string } const defaultMaxAttachmentSize = utils.ByteSize(10 * 1024 * 1024) // 10Mb diff --git a/server/webhook_jira.go b/server/webhook_jira.go index ca5d1a6b3..02ac5c522 100644 --- a/server/webhook_jira.go +++ b/server/webhook_jira.go @@ -63,6 +63,17 @@ func (jwh *JiraWebhook) expandIssue(p *Plugin, instanceID types.ID) error { if err != nil { // User is not connected, so we try to fall back to JWT bot if instance.JWTInstance == nil { + // Using API token to fetch the issue details as users were not getting notified for the events triggered by a non connected user i.e. oauth token is absent + if p.getConfig().AdminAPIToken != "" { + issue, apiTokenErr := p.GetIssueDataWithAPIToken(jwh.Issue.Key, instance.GetID().String()) + if apiTokenErr != nil { + return apiTokenErr + } + + jwh.Issue = *issue + return nil + } + return errors.Wrap(err, "Cannot create subscription posts for this comment as the Jira comment author is not connected to Mattermost.") } From e9a9da4d32b7db0b9be5bfc507611311f83bda85 Mon Sep 17 00:00:00 2001 From: kshitij katiyar <90389917+Kshitij-Katiyar@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:12:04 +0530 Subject: [PATCH 03/10] [MM-769]: Convert some JS files to TS and removed unused codes (#1124) --- webapp/src/action_types/{index.js => index.ts} | 0 webapp/src/client/{index.js => index.ts} | 15 ++++++++++++--- webapp/src/reducers/index.js | 13 ------------- webapp/src/selectors/index.ts | 2 -- 4 files changed, 12 insertions(+), 18 deletions(-) rename webapp/src/action_types/{index.js => index.ts} (100%) rename webapp/src/client/{index.js => index.ts} (74%) diff --git a/webapp/src/action_types/index.js b/webapp/src/action_types/index.ts similarity index 100% rename from webapp/src/action_types/index.js rename to webapp/src/action_types/index.ts diff --git a/webapp/src/client/index.js b/webapp/src/client/index.ts similarity index 74% rename from webapp/src/client/index.js rename to webapp/src/client/index.ts index 16b4811f1..e17ce73b4 100644 --- a/webapp/src/client/index.js +++ b/webapp/src/client/index.ts @@ -4,13 +4,22 @@ import {Client4} from 'mattermost-redux/client'; import {ClientError} from 'mattermost-redux/client/client4'; -export const doFetch = async (url, options) => { +interface QueryParameters { + [key: string]: string | number | boolean; +} + +interface FetchOptions { + method: string; + body?: BodyInit | null; +} + +export const doFetch = async (url: string, options: FetchOptions) => { const {data} = await doFetchWithResponse(url, options); return data; }; -export const doFetchWithResponse = async (url, options = {}) => { +export const doFetchWithResponse = async (url: string, options = {}) => { const response = await fetch(url, Client4.getOptions(options)); let data; @@ -32,7 +41,7 @@ export const doFetchWithResponse = async (url, options = {}) => { }); }; -export function buildQueryString(parameters) { +export function buildQueryString(parameters: QueryParameters) { const keys = Object.keys(parameters); if (keys.length === 0) { return ''; diff --git a/webapp/src/reducers/index.js b/webapp/src/reducers/index.js index d68df9726..efed52332 100644 --- a/webapp/src/reducers/index.js +++ b/webapp/src/reducers/index.js @@ -193,18 +193,6 @@ const channelSubscriptions = (state = {}, action) => { } }; -const storedLinkTooltipIssue = (state = {}, action) => { - switch (action.type) { - case ActionTypes.RECEIVED_JIRA_TICKET : { - return { - ticket: action.data, - }; - } - default: - return state; - } -}; - export default combineReducers({ userConnected, userCanConnect, @@ -220,5 +208,4 @@ export default combineReducers({ attachCommentToIssueModalForPostId, channelIdWithSettingsOpen, channelSubscriptions, - storedLinkTooltipIssue, }); diff --git a/webapp/src/selectors/index.ts b/webapp/src/selectors/index.ts index 0694f25cd..0488f67a4 100644 --- a/webapp/src/selectors/index.ts +++ b/webapp/src/selectors/index.ts @@ -73,5 +73,3 @@ export const instanceIsInstalled = (state): boolean => getInstalledInstances(sta export const getDefaultUserInstanceID = (state) => getPluginState(state).defaultUserInstanceID; export const getPluginSettings = (state) => getPluginState(state).pluginSettings; - -export const getStoredLinkTooltipIssue = (state) => getPluginState(state).storedLinkTooltipIssue; From a5d3c8165b8eb42ffb32ae0ccc54d233d1282863 Mon Sep 17 00:00:00 2001 From: kshitij katiyar <90389917+Kshitij-Katiyar@users.noreply.github.com> Date: Thu, 24 Oct 2024 16:46:53 +0530 Subject: [PATCH 04/10] [MM-987]: Added setup and webhook command to system admin help text (#1125) --- server/command.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/command.go b/server/command.go index 9f877e96b..192b0fa91 100644 --- a/server/command.go +++ b/server/command.go @@ -81,6 +81,9 @@ const commonHelpText = "\n" + "" const sysAdminHelpText = "\n###### For System Administrators:\n" + + "Setup Jira plugin\n" + + "* `/jira setup` - Start Jira plugin setup flow\n" + + "* `/jira webhook [jiraURL]` - Display the webhook URLs to setup on Jira\n" + "Install Jira instances:\n" + "* `/jira instance install server [jiraURL]` - Connect Mattermost to a Jira Server or Data Center instance located at \n" + "* `/jira instance install cloud-oauth [jiraURL]` - Connect Mattermost to a Jira Cloud instance using OAuth 2.0 located at \n" + @@ -94,7 +97,6 @@ const sysAdminHelpText = "\n###### For System Administrators:\n" + "* `/jira instance alias [URL] [alias-name]` - assign an alias to an instance\n" + "* `/jira instance unalias [alias-name]` - remve an alias from an instance\n" + "* `/jira instance v2 ` - Set the Jira instance to process \"v2\" webhooks and subscriptions (not prefixed with the instance ID)\n" + - "* `/jira webhook [--instance=]` - Show the Mattermost webhook to receive JQL queries\n" + "* `/jira v2revert ` - Revert to V2 jira plugin data model\n" + "" From dc1f1e23914d86f6fe0c4f5a62379012567651e4 Mon Sep 17 00:00:00 2001 From: kshitij katiyar <90389917+Kshitij-Katiyar@users.noreply.github.com> Date: Tue, 12 Nov 2024 04:21:29 +0530 Subject: [PATCH 05/10] Fixing failing CI by updating golangcilint version (#1136) * Updating golangcilint version * degrade the golangci lint version * upgraded the golangci-lint version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4ba8cbeb5..c4644d79f 100644 --- a/Makefile +++ b/Makefile @@ -158,7 +158,7 @@ apply: ## Install go tools install-go-tools: @echo Installing go tools - $(GO) install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.1 + $(GO) install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.0 $(GO) install gotest.tools/gotestsum@v1.7.0 ## Runs eslint and golangci-lint From b54d4c65405e71f027d96ae5c1e6bc888bdfe57f Mon Sep 17 00:00:00 2001 From: kshitij katiyar <90389917+Kshitij-Katiyar@users.noreply.github.com> Date: Tue, 12 Nov 2024 15:40:23 +0530 Subject: [PATCH 06/10] [MM-1028]: Fixed the issue of title being truncated without ellipses in tooltip modal (#1123) * [MM-1028]: Fixed the issue of title being truncated without ellipses in tooltip modal * [MM-1028]: Updated the handling of jira summary in tooltip * [MM-1028]: review fixes * [MM-1028]: Added hover text to tooltip title --- .../jira_ticket_tooltip/jira_ticket_tooltip.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/webapp/src/components/jira_ticket_tooltip/jira_ticket_tooltip.tsx b/webapp/src/components/jira_ticket_tooltip/jira_ticket_tooltip.tsx index 7501fd937..8caa3c0cd 100644 --- a/webapp/src/components/jira_ticket_tooltip/jira_ticket_tooltip.tsx +++ b/webapp/src/components/jira_ticket_tooltip/jira_ticket_tooltip.tsx @@ -167,6 +167,11 @@ export default class TicketPopover extends React.PureComponent { } const {ticketDetails} = this.state; + + // Format the ticket summary by trimming spaces, replacing multiple spaces with one, truncating to `jiraTicketSummaryMaxLength`, and adding '...' if it exceeds the limit. + const formattedSummary = ticketDetails?.summary ? `${ticketDetails.summary.trim().split(/\s+/).join(' ') + .substring(0, jiraTicketSummaryMaxLength)}${ticketDetails.summary.trim().split(/\s+/).join(' ').length > jiraTicketSummaryMaxLength ? '...' : ''}` : ''; + if (!ticketDetails) { // Display the spinner loader while ticket details are being fetched return ( @@ -204,9 +209,10 @@ export default class TicketPopover extends React.PureComponent { -
{ticketDetails.summary && ticketDetails.summary.substring(0, jiraTicketSummaryMaxLength)}
+
{formattedSummary}
{this.tagTicketStatus(ticketDetails.statusKey)} From 9fa88f19c0dc40fe0245a67b19689679da6bbda8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 21:07:26 -0500 Subject: [PATCH 07/10] Bump cross-spawn from 7.0.3 to 7.0.6 in /webapp (#1144) Bumps [cross-spawn](https://github.com/moxystudio/node-cross-spawn) from 7.0.3 to 7.0.6. - [Changelog](https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md) - [Commits](https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.6) --- updated-dependencies: - dependency-name: cross-spawn dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- webapp/package-lock.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 8e603ba48..737902e2e 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -8053,7 +8053,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", From 6a7a70ff2092c60b95d789ffdb0ecbe0d8bc34b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 21:43:07 -0500 Subject: [PATCH 08/10] Bump github.com/golang-jwt/jwt/v4 from 4.4.2 to 4.5.1 (#1138) Bumps [github.com/golang-jwt/jwt/v4](https://github.com/golang-jwt/jwt) from 4.4.2 to 4.5.1. - [Release notes](https://github.com/golang-jwt/jwt/releases) - [Changelog](https://github.com/golang-jwt/jwt/blob/main/VERSION_HISTORY.md) - [Commits](https://github.com/golang-jwt/jwt/compare/v4.4.2...v4.5.1) --- updated-dependencies: - dependency-name: github.com/golang-jwt/jwt/v4 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 9bc47d00f..b0ea28433 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/francoispqt/gojay v1.2.13 // indirect github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect - github.com/golang-jwt/jwt/v4 v4.4.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.1 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.6.0 // indirect diff --git a/go.sum b/go.sum index bdc0baeb7..fb58eaccb 100644 --- a/go.sum +++ b/go.sum @@ -308,8 +308,9 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= +github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-migrate/migrate/v4 v4.14.1/go.mod h1:l7Ks0Au6fYHuUIxUhQ0rcVX1uLlJg54C/VvW7tvxSz0= From a8d24033956f4fd26a1264983889b0b807930620 Mon Sep 17 00:00:00 2001 From: Ben Schumacher Date: Tue, 10 Dec 2024 09:20:59 +0100 Subject: [PATCH 09/10] [MM-61121] Add diagnostics data to the Support Packet (#1131) Co-authored-by: kshitij katiyar --- go.mod | 8 ++-- go.sum | 4 +- server/support_packet.go | 59 +++++++++++++++++++++++++++ server/telemetry.go | 87 ++++++++++++++++++++++++++-------------- 4 files changed, 123 insertions(+), 35 deletions(-) create mode 100644 server/support_packet.go diff --git a/go.mod b/go.mod index b0ea28433..a65bfc49c 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/mattermost/mattermost-plugin-jira go 1.22 -toolchain go1.22.2 +toolchain go1.22.8 require ( github.com/andygrunwald/go-jira v1.16.0 @@ -10,9 +10,10 @@ require ( github.com/dghubble/oauth1 v0.5.0 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/gorilla/mux v1.8.1 + github.com/hashicorp/go-multierror v1.1.1 github.com/jarcoal/httpmock v1.0.8 github.com/mattermost/mattermost-plugin-autolink v1.2.2-0.20210709183311-c8fa30db649f - github.com/mattermost/mattermost/server/public v0.1.7 + github.com/mattermost/mattermost/server/public v0.1.9 github.com/pkg/errors v0.9.1 github.com/rbriski/atlassian-jwt v0.0.0-20240408161306-6b6d681cf2d9 github.com/rudderlabs/analytics-go v3.3.3+incompatible @@ -20,6 +21,7 @@ require ( github.com/trivago/tgo v1.0.7 golang.org/x/oauth2 v0.21.0 golang.org/x/text v0.16.0 + gopkg.in/yaml.v3 v3.0.1 ) require ( @@ -38,7 +40,6 @@ require ( github.com/gorilla/websocket v1.5.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-plugin v1.6.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/klauspost/compress v1.15.14 // indirect @@ -79,5 +80,4 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index fb58eaccb..f41036d92 100644 --- a/go.sum +++ b/go.sum @@ -630,8 +630,8 @@ github.com/mattermost/mattermost-plugin-autolink v1.2.2-0.20210709183311-c8fa30d github.com/mattermost/mattermost-plugin-autolink v1.2.2-0.20210709183311-c8fa30db649f/go.mod h1:JO5RQqTYL2D1zDz7+5ucAmNeRMiudDvZQoRtqbm+1sU= github.com/mattermost/mattermost-server/v5 v5.3.2-0.20210621071817-df224571d8a1 h1:5/lZibP83SrOpuKs4fE782pfWNFX/QTWwO2PuJJwGJ4= github.com/mattermost/mattermost-server/v5 v5.3.2-0.20210621071817-df224571d8a1/go.mod h1:S3zT7H4bAxsev1d2ThoSRBhyEXZa6JZOfpxvy2B25y4= -github.com/mattermost/mattermost/server/public v0.1.7 h1:WA+fnLrQQeE6xTyHERqcGiKljBFK6m8WYL4Pez07ko4= -github.com/mattermost/mattermost/server/public v0.1.7/go.mod h1:SkTKbMul91Rq0v2dIxe8mqzUOY+3KwlwwLmAlxDfGCk= +github.com/mattermost/mattermost/server/public v0.1.9 h1:l/OKPRVuFeqL0yqRVC/JpveG5sLNKcT9llxqMkO9e+s= +github.com/mattermost/mattermost/server/public v0.1.9/go.mod h1:SkTKbMul91Rq0v2dIxe8mqzUOY+3KwlwwLmAlxDfGCk= github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0/go.mod h1:nV5bfVpT//+B1RPD2JvRnxbkLmJEYXmRaaVl15fsXjs= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= diff --git a/server/support_packet.go b/server/support_packet.go new file mode 100644 index 000000000..2475ab13b --- /dev/null +++ b/server/support_packet.go @@ -0,0 +1,59 @@ +package main + +import ( + "path/filepath" + + "github.com/hashicorp/go-multierror" + "github.com/pkg/errors" + "gopkg.in/yaml.v3" + + "github.com/mattermost/mattermost/server/public/model" + "github.com/mattermost/mattermost/server/public/plugin" +) + +type SupportPacket struct { + Version string `yaml:"version"` + + InstanceCount int `yaml:"instance_count"` + ServerInstanceCount int `yaml:"server_instance_count"` + CloudInstanceCount int `yaml:"cloud_instance_count"` + SubscriptionCount int `yaml:"subscription_count"` + ConnectedUserCount int `yaml:"connected_user_count"` +} + +func (p *Plugin) GenerateSupportData(_ *plugin.Context) ([]*model.FileData, error) { + var result *multierror.Error + + connectedUserCount, err := p.userCount() + if err != nil { + result = multierror.Append(result, errors.Wrap(err, "failed to get the number of connected users for Support Packet")) + } + + serverICount, cloudICount, err := p.instanceCount() + if err != nil { + result = multierror.Append(result, errors.Wrap(err, "failed to get the number of instances for Support Packet")) + } + + subscriptionCount, err := p.subscriptionCount() + if err != nil { + result = multierror.Append(result, errors.Wrap(err, "failed to get the number of subscriptions for Support Packet")) + } + + diagnostics := SupportPacket{ + Version: manifest.Version, + InstanceCount: serverICount + cloudICount, + ServerInstanceCount: serverICount, + CloudInstanceCount: cloudICount, + SubscriptionCount: subscriptionCount, + ConnectedUserCount: connectedUserCount, + } + body, err := yaml.Marshal(diagnostics) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal diagnostics") + } + + return []*model.FileData{{ + Filename: filepath.Join(manifest.Id, "diagnostics.yaml"), + Body: body, + }}, result.ErrorOrNil() +} diff --git a/server/telemetry.go b/server/telemetry.go index eeaca3724..fdaf663e0 100644 --- a/server/telemetry.go +++ b/server/telemetry.go @@ -1,6 +1,8 @@ package main import ( + "github.com/pkg/errors" + "github.com/mattermost/mattermost-plugin-jira/server/telemetry" ) @@ -22,52 +24,79 @@ func (p *Plugin) OnSendDailyTelemetry() { args := map[string]interface{}{} // Jira instances - server, cloud := 0, 0 - instances, err := p.instanceStore.LoadInstances() + serverICount, cloudICount, err := p.instanceCount() if err != nil { p.client.Log.Warn("Failed to get instances for telemetry", "error", err) } else { - for _, id := range instances.IDs() { - switch instances.Get(id).Type { - case ServerInstanceType: - server++ - case CloudInstanceType: - cloud++ - } - } - args["instance_count"] = server + cloud - if server > 0 { - args["server_instance_count"] = server - } - if cloud > 0 { - args["cloud_instance_count"] = cloud + args["instance_count"] = serverICount + cloudICount + if serverICount > 0 { + args["server_instance_count"] = serverICount } - - // Subscriptions - numSubscriptions := 0 - var subs *Subscriptions - for _, id := range instances.IDs() { - subs, err = p.getSubscriptions(id) - if err != nil { - p.client.Log.Warn("Failed to get subscriptions for telemetry", "error", err) - } - numSubscriptions += len(subs.Channel.ByID) + if cloudICount > 0 { + args["cloud_instance_count"] = cloudICount } + } - args["subscriptions"] = numSubscriptions + subscriptionCount, err := p.subscriptionCount() + if err != nil { + p.client.Log.Warn("Failed to get the number of subscriptions for telemetry", "error", err) + } else { + args["subscriptions"] = subscriptionCount } // Connected users - connected, err := p.userStore.CountUsers() + connectedUsers, err := p.userCount() if err != nil { p.client.Log.Warn("Failed to get the number of connected users for telemetry", "error", err) } else { - args["connected_user_count"] = connected + args["connected_user_count"] = connectedUsers } p.TrackEvent("stats", args) } +func (p *Plugin) instanceCount() (server int, cloud int, err error) { + instances, err := p.instanceStore.LoadInstances() + if err != nil { + return + } + + for _, id := range instances.IDs() { + switch instances.Get(id).Type { + case ServerInstanceType: + server++ + case CloudInstanceType: + cloud++ + } + } + + return +} + +func (p *Plugin) subscriptionCount() (int, error) { + instances, err := p.instanceStore.LoadInstances() + if err != nil { + return 0, err + } + + // Subscriptions + numSubscriptions := 0 + var subs *Subscriptions + for _, id := range instances.IDs() { + subs, err = p.getSubscriptions(id) + if err != nil { + return 0, errors.Wrapf(err, "failed to get subscription %q for telemetry", id) + } + numSubscriptions += len(subs.Channel.ByID) + } + + return numSubscriptions, nil +} + +func (p *Plugin) userCount() (int, error) { + return p.userStore.CountUsers() +} + // Initialize telemetry setups the tracker/clients needed to send telemetry data. // The telemetry.NewTrackerConfig(...) param will take care of extract/parse the config to set the right settings. // If you don't want the default behavior you still can pass a different telemetry.TrackerConfig data. From 4bcc7d9dd28587e0cbf377795a9147372e5fb028 Mon Sep 17 00:00:00 2001 From: kshitij katiyar <90389917+Kshitij-Katiyar@users.noreply.github.com> Date: Thu, 9 Jan 2025 17:15:09 +0530 Subject: [PATCH 10/10] [MM-1137]: Added Autolink support for cloud-oauth (#1139) * [MM-1137]: Added autolink support for cloud-oauth * [MM-1137]: Adding encryption key field in plugin config and encrypting admin api token * [MM-1137]: Added testcases for setupAutolink function * [MM-1137]: Updated AdminAPIToken help text * [MM-1137]: Review fixes * [MM-1137]: review fixes * [MM-1137]: log errors * Review fixes Co-authored-by: Doug Lauder * [MM-1137]: Fixed the secrets error found by QA * [MM-1137]: Fixed the invalid log after successfully installing autolink --------- Co-authored-by: Raghav Aggarwal Co-authored-by: Doug Lauder --- plugin.json | 20 +++++- server/issue.go | 49 ++++++++++++++- server/kv_mock_test.go | 22 ++++--- server/plugin.go | 134 ++++++++++++++++++++++++++++++--------- server/plugin_test.go | 138 +++++++++++++++++++++++++++++++++++++++++ server/utils.go | 23 +++++++ 6 files changed, 345 insertions(+), 41 deletions(-) diff --git a/plugin.json b/plugin.json index 7488278fe..3474f71b1 100644 --- a/plugin.json +++ b/plugin.json @@ -115,11 +115,29 @@ "placeholder": "", "default": false }, + { + "key": "EncryptionKey", + "display_name": "At Rest Encryption Key:", + "type": "generated", + "help_text": "The encryption key used to encrypt stored API tokens.", + "placeholder": "", + "default": null, + "secret": true + }, { "key": "AdminAPIToken", "display_name": "Admin API Token", "type": "text", - "help_text": "Set this [API token](https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/) to get notified for comment and issue created events even if the user triggering the event is not connected to Jira.\n **Note:** API token should be created using an admin Jira account. Otherwise, the notification will not be delivered for the project the user cannot access.", + "help_text": "Set this [API token](https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/) to get notified for comment and issue created events when the user triggering the event is not connected to Jira. This is also used for setting up autolink in the plugin.\n **Note:** API token should be created using an admin Jira account. Otherwise, the notification will not be delivered for projects that the user cannot access and autolink will not work.", + "placeholder": "", + "secret": true, + "default": "" + }, + { + "key": "AdminEmail", + "display_name": "Admin Email", + "type": "text", + "help_text": "**Note** Admin email is necessary to setup autolink for the Jira plugin and to to get notified for comment and issue created events when the user triggering the event is not connected to Jira", "placeholder": "", "default": "" } diff --git a/server/issue.go b/server/issue.go index f498d5bea..bdcc71e64 100644 --- a/server/issue.go +++ b/server/issue.go @@ -1103,7 +1103,10 @@ func (p *Plugin) GetIssueDataWithAPIToken(issueID, instanceID string) (*jira.Iss return nil, errors.Wrapf(err, "failed to create http request for fetching issue data. IssueID: %s", issueID) } - req.Header.Set("Authorization", fmt.Sprintf("Basic %s", p.getConfig().AdminAPIToken)) + err = p.SetAdminAPITokenRequestHeader(req) + if err != nil { + return nil, err + } resp, err := client.Do(req) if err != nil { @@ -1134,3 +1137,47 @@ func (p *Plugin) GetIssueDataWithAPIToken(issueID, instanceID string) (*jira.Iss return issue, nil } + +type ProjectSearchResponse struct { + Self string `json:"self"` + MaxResults int `json:"maxResults"` + StartAt int `json:"startAt"` + Total int `json:"total"` + IsLast bool `json:"isLast"` + Values jira.ProjectList `json:"values"` +} + +func (p *Plugin) GetProjectListWithAPIToken(instanceID string) (*jira.ProjectList, error) { + client := &http.Client{} + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/rest/api/3/project/search", instanceID), nil) + if err != nil { + return nil, errors.Wrapf(err, "failed to create HTTP request for fetching project list data. InstanceID: %s", instanceID) + } + + err = p.SetAdminAPITokenRequestHeader(req) + if err != nil { + return nil, err + } + + resp, err := client.Do(req) + if err != nil { + return nil, errors.Wrapf(err, "failed to fetch project list data. InstanceID: %s", instanceID) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, errors.Errorf("unexpected status code: %d. InstanceID: %s", resp.StatusCode, instanceID) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, errors.Wrap(err, "failed to read response body") + } + + var projectResponse ProjectSearchResponse + if err = json.Unmarshal(body, &projectResponse); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal project list response") + } + + return &projectResponse.Values, nil +} diff --git a/server/kv_mock_test.go b/server/kv_mock_test.go index b5b90e016..fe750bbcd 100644 --- a/server/kv_mock_test.go +++ b/server/kv_mock_test.go @@ -9,6 +9,7 @@ import ( jira "github.com/andygrunwald/go-jira" "github.com/pkg/errors" + "github.com/stretchr/testify/mock" "github.com/mattermost/mattermost-plugin-jira/server/utils/types" ) @@ -98,26 +99,29 @@ func (store mockUserStore) MapUsers(func(*User) error) error { return nil } -type mockInstanceStore struct{} +type mockInstanceStore struct { + mock.Mock +} -func (store mockInstanceStore) CreateInactiveCloudInstance(types.ID, string) error { +func (store *mockInstanceStore) CreateInactiveCloudInstance(types.ID, string) error { return nil } -func (store mockInstanceStore) DeleteInstance(types.ID) error { +func (store *mockInstanceStore) DeleteInstance(types.ID) error { return nil } -func (store mockInstanceStore) LoadInstance(types.ID) (Instance, error) { - return &testInstance{}, nil +func (store *mockInstanceStore) LoadInstance(id types.ID) (Instance, error) { + args := store.Called(id) + return args.Get(0).(Instance), args.Error(1) } -func (store mockInstanceStore) LoadInstanceFullKey(string) (Instance, error) { +func (store *mockInstanceStore) LoadInstanceFullKey(string) (Instance, error) { return &testInstance{}, nil } -func (store mockInstanceStore) LoadInstances() (*Instances, error) { +func (store *mockInstanceStore) LoadInstances() (*Instances, error) { return NewInstances(), nil } -func (store mockInstanceStore) StoreInstance(instance Instance) error { +func (store *mockInstanceStore) StoreInstance(instance Instance) error { return nil } -func (store mockInstanceStore) StoreInstances(*Instances) error { +func (store *mockInstanceStore) StoreInstances(*Instances) error { return nil } diff --git a/server/plugin.go b/server/plugin.go index 02b5c34c5..22766170b 100644 --- a/server/plugin.go +++ b/server/plugin.go @@ -18,6 +18,7 @@ import ( "sync" textTemplate "text/template" + "github.com/andygrunwald/go-jira" "github.com/gorilla/mux" "github.com/pkg/errors" @@ -82,8 +83,14 @@ type externalConfig struct { // Display subscription name in notifications DisplaySubscriptionNameInNotifications bool + // The encryption key used to encrypt stored api tokens + EncryptionKey string + // API token from Jira AdminAPIToken string + + // Email of the admin + AdminEmail string } const defaultMaxAttachmentSize = utils.ByteSize(10 * 1024 * 1024) // 10Mb @@ -179,6 +186,25 @@ func (p *Plugin) OnConfigurationChange() error { } } + jsonBytes, err := json.Marshal(ec.AdminAPIToken) + if err != nil { + p.client.Log.Warn("Error marshaling the admin API token", "error", err.Error()) + return err + } + + encryptionKey := ec.EncryptionKey + if encryptionKey == "" { + p.client.Log.Warn("Encryption key required to encrypt admin API token") + return errors.New("failed to encrypt admin token. Encryption key not generated") + } + + encryptedAdminAPIToken, err := encrypt(jsonBytes, []byte(encryptionKey)) + if err != nil { + p.client.Log.Warn("Error encrypting the admin API token", "error", err.Error()) + return err + } + ec.AdminAPIToken = string(encryptedAdminAPIToken) + prev := p.getConfig() p.updateConfig(func(conf *config) { conf.externalConfig = ec @@ -309,34 +335,7 @@ func (p *Plugin) OnActivate() error { p.enterpriseChecker = enterprise.NewEnterpriseChecker(p.API) go func() { - for _, url := range instances.IDs() { - var instance Instance - instance, err = p.instanceStore.LoadInstance(url) - if err != nil { - continue - } - - ci, ok := instance.(*cloudInstance) - if !ok { - p.client.Log.Info("only cloud instances supported for autolink", "err", err) - continue - } - var status *model.PluginStatus - status, err = p.client.Plugin.GetPluginStatus(autolinkPluginID) - if err != nil { - p.client.Log.Warn("OnActivate: Autolink plugin unavailable. API returned error", "error", err.Error()) - continue - } - if status.State != model.PluginStateRunning { - p.client.Log.Warn("OnActivate: Autolink plugin unavailable. Plugin is not running", "status", status) - continue - } - - if err = p.AddAutolinksForCloudInstance(ci); err != nil { - p.client.Log.Info("could not install autolinks for cloud instance", "instance", ci.BaseURL, "err", err) - continue - } - } + p.SetupAutolink(instances) }() p.initializeTelemetry() @@ -344,6 +343,55 @@ func (p *Plugin) OnActivate() error { return nil } +func (p *Plugin) SetupAutolink(instances *Instances) { + for _, url := range instances.IDs() { + var instance Instance + instance, err := p.instanceStore.LoadInstance(url) + if err != nil { + continue + } + + if p.getConfig().AdminAPIToken == "" || p.getConfig().AdminEmail == "" { + p.client.Log.Info("unable to setup autolink due to missing API Token or Admin Email") + continue + } + + switch instance.(type) { + case *cloudInstance, *cloudOAuthInstance: + default: + p.client.Log.Info("only cloud and cloud-oauth instances supported for autolink") + continue + } + + var status *model.PluginStatus + status, err = p.client.Plugin.GetPluginStatus(autolinkPluginID) + if err != nil { + p.client.Log.Warn("OnActivate: Autolink plugin unavailable. API returned error", "error", err.Error()) + continue + } + + if status.State != model.PluginStateRunning { + p.client.Log.Warn("OnActivate: Autolink plugin unavailable. Plugin is not running", "status", status) + continue + } + + switch instance := instance.(type) { + case *cloudInstance: + if err = p.AddAutolinksForCloudInstance(instance); err != nil { + p.client.Log.Info("could not install autolinks for cloud instance", "instance", instance.BaseURL, "error", err.Error()) + } else { + p.client.Log.Info("successfully installed autolinks for cloud instance", "instance", instance.BaseURL) + } + case *cloudOAuthInstance: + if err = p.AddAutolinksForCloudOAuthInstance(instance); err != nil { + p.client.Log.Info("could not install autolinks for cloud-oauth instance", "instance", instance.JiraBaseURL, "error", err.Error()) + } else { + p.client.Log.Info("successfully installed autolinks for cloud-oauth instance", "instance", instance.JiraBaseURL) + } + } + } +} + func (p *Plugin) AddAutolinksForCloudInstance(ci *cloudInstance) error { client, err := ci.getClientForBot() if err != nil { @@ -355,9 +403,23 @@ func (p *Plugin) AddAutolinksForCloudInstance(ci *cloudInstance) error { return fmt.Errorf("unable to get project keys: %w", err) } + return p.AddAutoLinkForProjects(plist, ci.BaseURL) +} + +func (p *Plugin) AddAutolinksForCloudOAuthInstance(coi *cloudOAuthInstance) error { + plist, err := p.GetProjectListWithAPIToken(string(coi.InstanceID)) + if err != nil { + return fmt.Errorf("error getting project list: %w", err) + } + + return p.AddAutoLinkForProjects(*plist, coi.JiraBaseURL) +} + +func (p *Plugin) AddAutoLinkForProjects(plist jira.ProjectList, baseURL string) error { + var err error for _, proj := range plist { key := proj.Key - err = p.AddAutolinks(key, ci.BaseURL) + err = p.AddAutolinks(key, baseURL) } if err != nil { return fmt.Errorf("some keys were not installed: %w", err) @@ -383,7 +445,10 @@ func (p *Plugin) AddAutolinks(key, baseURL string) error { client := autolinkclient.NewClientPlugin(p.API) if err := client.Add(installList...); err != nil { - return fmt.Errorf("unable to add autolinks: %w", err) + // Do not return an error if the status code is 304 (indicating that the autolink for this project is already installed). + if !strings.Contains(err.Error(), `Error: 304, {"status": "OK"}`) { + return fmt.Errorf("unable to add autolinks: %w", err) + } } return nil @@ -482,6 +547,15 @@ func (c *externalConfig) setDefaults() (bool, error) { changed = true } + if c.EncryptionKey == "" { + encryptionKey, err := generateSecret() + if err != nil { + return false, err + } + c.EncryptionKey = encryptionKey + changed = true + } + return changed, nil } diff --git a/server/plugin_test.go b/server/plugin_test.go index b268a213b..d1155859a 100644 --- a/server/plugin_test.go +++ b/server/plugin_test.go @@ -19,6 +19,16 @@ import ( "github.com/stretchr/testify/assert" ) +const ( + MockInstanceID = "mockInstanceID" + MockAPIToken = "mockAPIToken" + MockAdminEmail = "mockadmin@email.com" + MockBaseURL = "mockBaseURL" + MockASCKey = "mockAtlassianSecurityContextKey" + MockASCClientKey = "mockAtlassianSecurityContextClientKey" + MockASCSharedSecret = "mockAtlassianSecurityContextSharedSecret" // #nosec G101: Potential hardcoded credentials - This is a mock for testing purposes +) + func validRequestBody() io.ReadCloser { if f, err := os.Open("testdata/webhook-issue-created.json"); err != nil { panic(err) @@ -144,3 +154,131 @@ func TestPlugin(t *testing.T) { }) } } + +func TestSetupAutolink(t *testing.T) { + tests := []struct { + name string + setup func(*Plugin, *plugintest.API, *mockInstanceStore) + InstanceType InstanceType + }{ + { + name: "Missing API token or Admin email", + setup: func(p *Plugin, mockAPI *plugintest.API, dummyInstanceStore *mockInstanceStore) { + mockAPI.On("LogInfo", "unable to setup autolink due to missing API Token or Admin Email").Return(nil).Times(1) + dummyInstanceStore.On("LoadInstance", mock.Anything).Return(&serverInstance{}, nil).Times(1) + + p.updateConfig(func(c *config) { + c.AdminAPIToken = "" + c.AdminEmail = "" + }) + }, + InstanceType: ServerInstanceType, + }, + { + name: "Unsupported instance type", + setup: func(p *Plugin, mockAPI *plugintest.API, dummyInstanceStore *mockInstanceStore) { + mockAPI.On("LogInfo", "only cloud and cloud-oauth instances supported for autolink").Return(nil).Times(1) + dummyInstanceStore.On("LoadInstance", mock.Anything).Return(&serverInstance{}, nil).Times(1) + + p.updateConfig(GetConfigSetterFunction()) + }, + InstanceType: ServerInstanceType, + }, + { + name: "Autolink plugin unavailable API returned error", + setup: func(p *Plugin, mockAPI *plugintest.API, dummyInstanceStore *mockInstanceStore) { + mockAPI.On("LogWarn", "OnActivate: Autolink plugin unavailable. API returned error", "error", mock.Anything).Return(nil).Times(1) + mockAPI.On("GetPluginStatus", autolinkPluginID).Return(nil, &model.AppError{Message: "error getting plugin status"}).Times(1) + dummyInstanceStore.On("LoadInstance", mock.Anything).Return(&cloudInstance{}, nil).Times(1) + + p.updateConfig(GetConfigSetterFunction()) + }, + InstanceType: CloudInstanceType, + }, + { + name: "Autolink plugin not running", + setup: func(p *Plugin, mockAPI *plugintest.API, dummyInstanceStore *mockInstanceStore) { + mockAPI.On("LogWarn", "OnActivate: Autolink plugin unavailable. Plugin is not running", "status", &model.PluginStatus{State: model.PluginStateNotRunning}).Return(nil).Times(1) + mockAPI.On("GetPluginStatus", autolinkPluginID).Return(&model.PluginStatus{State: model.PluginStateNotRunning}, nil).Times(1) + dummyInstanceStore.On("LoadInstance", mock.Anything).Return(&cloudInstance{}, nil).Times(1) + + p.updateConfig(GetConfigSetterFunction()) + }, + InstanceType: CloudInstanceType, + }, + { + name: "Error installing autolinks for cloud instance", + setup: func(p *Plugin, mockAPI *plugintest.API, dummyInstanceStore *mockInstanceStore) { + mockAPI.On("LogInfo", "could not install autolinks for cloud instance", "instance", "mockBaseURL", "error", mock.Anything).Return(nil).Times(1) + mockAPI.On("GetPluginStatus", autolinkPluginID).Return(&model.PluginStatus{State: model.PluginStateRunning}, nil).Times(1) + dummyInstanceStore.On("LoadInstance", mock.Anything).Return( + &cloudInstance{ + InstanceCommon: &InstanceCommon{ + Plugin: p, + }, + AtlassianSecurityContext: &AtlassianSecurityContext{ + BaseURL: MockBaseURL, + Key: MockASCKey, + ClientKey: MockASCClientKey, + SharedSecret: MockASCSharedSecret, + }, + }, nil).Times(1) + + p.updateConfig(GetConfigSetterFunction()) + }, + InstanceType: CloudInstanceType, + }, + { + name: "Error installing autolinks for cloud-oauth instance", + setup: func(p *Plugin, mockAPI *plugintest.API, dummyInstanceStore *mockInstanceStore) { + mockAPI.On("LogWarn", "Error unmarshalling admin API token", "error", mock.Anything).Times(1) + mockAPI.On("LogInfo", "could not install autolinks for cloud-oauth instance", "instance", "mockBaseURL", "error", mock.Anything).Return(nil).Times(1) + mockAPI.On("GetPluginStatus", autolinkPluginID).Return(&model.PluginStatus{State: model.PluginStateRunning}, nil).Times(1) + + dummyInstanceStore.On("LoadInstance", mock.Anything).Return( + &cloudOAuthInstance{ + InstanceCommon: &InstanceCommon{ + Plugin: p, + }, + JiraBaseURL: MockBaseURL, + }, nil).Times(1) + + p.updateConfig(GetConfigSetterFunction()) + }, + InstanceType: CloudOAuthInstanceType, + }, + } + for _, tt := range tests { + mockAPI := &plugintest.API{} + dummyInstanceStore := new(mockInstanceStore) + mockPluginClient := pluginapi.NewClient(mockAPI, nil) + p := &Plugin{ + client: mockPluginClient, + instanceStore: dummyInstanceStore, + } + + t.Run(tt.name, func(t *testing.T) { + tt.setup(p, mockAPI, dummyInstanceStore) + instances := GetInstancesWithType(tt.InstanceType) + + p.SetupAutolink(instances) + + mockAPI.AssertExpectations(t) + dummyInstanceStore.AssertExpectations(t) + }) + } +} + +func GetConfigSetterFunction() func(*config) { + return func(c *config) { + c.AdminAPIToken = MockAPIToken + c.AdminEmail = MockAdminEmail + } +} + +func GetInstancesWithType(instanceType InstanceType) *Instances { + return NewInstances(&InstanceCommon{ + InstanceID: MockInstanceID, + Type: instanceType, + }) +} diff --git a/server/utils.go b/server/utils.go index 21ba39089..0bda12115 100644 --- a/server/utils.go +++ b/server/utils.go @@ -7,7 +7,9 @@ import ( "crypto/rand" "crypto/sha256" "encoding/base64" + "encoding/json" "fmt" + "net/http" "regexp" "strings" @@ -182,3 +184,24 @@ func getS256PKCEParams() (*PKCEParams, error) { CodeVerifier: verifier, }, nil } + +func (p *Plugin) SetAdminAPITokenRequestHeader(req *http.Request) error { + encryptedAdminAPIToken := p.getConfig().AdminAPIToken + jsonBytes, err := decrypt([]byte(encryptedAdminAPIToken), []byte(p.getConfig().EncryptionKey)) + if err != nil { + p.client.Log.Warn("Error decrypting admin API token", "error", err.Error()) + return err + } + var adminAPIToken string + err = json.Unmarshal(jsonBytes, &adminAPIToken) + if err != nil { + p.client.Log.Warn("Error unmarshalling admin API token", "error", err.Error()) + return err + } + + encodedAuth := base64.StdEncoding.EncodeToString([]byte(p.getConfig().AdminEmail + ":" + adminAPIToken)) + req.Header.Set("Authorization", "Basic "+encodedAuth) + req.Header.Set("Accept", "application/json") + + return nil +}