generated from PenaSide/GolangTemplate
feat: init lf project
This commit is contained in:
parent
9526f3e32f
commit
35541bb9a3
3
Makefile
3
Makefile
@ -8,7 +8,8 @@ help: ## show this help
|
||||
|
||||
install: ## install all go dependencies
|
||||
go install \
|
||||
github.com/vektra/mockery/v2@v2.26.0
|
||||
github.com/vektra/mockery/v2@v2.26.0 \
|
||||
github.com/deepmap/oapi-codegen/cmd/oapi-codegen@v1.12.4
|
||||
|
||||
|
||||
test: ## run all layers tests
|
||||
|
@ -11,8 +11,8 @@ import (
|
||||
|
||||
formatter "github.com/antonfisher/nested-logrus-formatter"
|
||||
"github.com/sirupsen/logrus"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/app"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/initialize"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/app"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
20
go.mod
20
go.mod
@ -1,44 +1,49 @@
|
||||
module penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth
|
||||
module penahub.gitlab.yandexcloud.net/pena-services/customer
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/SevereCloud/vksdk/v2 v2.16.0
|
||||
github.com/antonfisher/nested-logrus-formatter v1.3.1
|
||||
github.com/deepmap/oapi-codegen v1.12.4
|
||||
github.com/getkin/kin-openapi v0.116.0
|
||||
github.com/go-resty/resty/v2 v2.7.0
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/labstack/echo v3.3.10+incompatible
|
||||
github.com/labstack/echo/v4 v4.10.2
|
||||
github.com/sethvargo/go-envconfig v0.9.0
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/stretchr/testify v1.8.2
|
||||
github.com/walkerus/go-wiremock v1.5.0
|
||||
go.mongodb.org/mongo-driver v1.11.4
|
||||
golang.org/x/oauth2 v0.6.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute/metadata v0.2.0 // indirect
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/swag v0.21.1 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/invopop/yaml v0.1.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/klauspost/compress v1.16.0 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/labstack/gommon v0.4.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||
github.com/perimeterx/marshmallow v1.1.4 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/objx v0.5.0 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.1 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.3 // indirect
|
||||
@ -52,5 +57,6 @@ require (
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
57
go.sum
57
go.sum
@ -1,15 +1,28 @@
|
||||
cloud.google.com/go/compute/metadata v0.2.0 h1:nBbNSZyDpkNlo3DepaaLKVuO7ClyifSAmNloSCZrHnQ=
|
||||
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||
github.com/SevereCloud/vksdk/v2 v2.16.0 h1:DQ90qqwY/yF1X/SWZQs1kQ/Ik+tphK82d+S6Rch46wQ=
|
||||
github.com/SevereCloud/vksdk/v2 v2.16.0/go.mod h1:VN6BH9nFUXcP7Uf0uX74Aht2DQ7+139aG3/Og+jia4w=
|
||||
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
|
||||
github.com/antonfisher/nested-logrus-formatter v1.3.1 h1:NFJIr+pzwv5QLHTPyKz9UMEoHck02Q9L0FP13b/xSbQ=
|
||||
github.com/antonfisher/nested-logrus-formatter v1.3.1/go.mod h1:6WTfyWFkBc9+zyBaKIqRrg/KwMqBbodBjgbHjDz7zjA=
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
|
||||
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
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/deepmap/oapi-codegen v1.12.4 h1:pPmn6qI9MuOtCz82WY2Xaw46EQjgvxednXXrP7g5Q2s=
|
||||
github.com/deepmap/oapi-codegen v1.12.4/go.mod h1:3lgHGMu6myQ2vqbbTXH2H1o4eXFTGnFiDaOaKKl5yas=
|
||||
github.com/getkin/kin-openapi v0.116.0 h1:o986hwgMzR972JzOG5j6+WTwWqllZLs1EJKMKCivs2E=
|
||||
github.com/getkin/kin-openapi v0.116.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU=
|
||||
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
|
||||
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
|
||||
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
||||
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
|
||||
@ -27,9 +40,15 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/invopop/yaml v0.1.0 h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc=
|
||||
github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
|
||||
github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
@ -41,12 +60,15 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
|
||||
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
|
||||
github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
|
||||
github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
|
||||
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
||||
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
@ -54,8 +76,13 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/perimeterx/marshmallow v1.1.4 h1:pZLDH9RjlLGGorbXhcaQLhfuV0pFMNfPO55FuFkxqLw=
|
||||
github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@ -67,29 +94,29 @@ github.com/sethvargo/go-envconfig v0.9.0 h1:Q6FQ6hVEeTECULvkJZakq3dZMeBQ3JUpcKMf
|
||||
github.com/sethvargo/go-envconfig v0.9.0/go.mod h1:Iz1Gy1Sf3T64TQlJSvee81qDhf7YIlt8GMUX6yyNFs0=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
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.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
|
||||
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
||||
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
|
||||
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
||||
github.com/walkerus/go-wiremock v1.5.0 h1:ipaYzaZnnOJRQS4wNFqz4YFphC/sM9GM+EiLEzv3KLc=
|
||||
github.com/walkerus/go-wiremock v1.5.0/go.mod h1:gMzQpReT5mG5T/PaW8pSFiPhazrcHb1mnf6JHdKwY5w=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
|
||||
@ -144,9 +171,15 @@ google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v2 v2.2.2/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-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0/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=
|
||||
|
@ -6,11 +6,11 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/initialize"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/server"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/closer"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/mongo"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/server"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/closer"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/mongo"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -1,43 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/client"
|
||||
)
|
||||
|
||||
type AmocrmClientDeps struct {
|
||||
Logger *logrus.Logger
|
||||
URLs *models.AmocrmURL
|
||||
}
|
||||
|
||||
type AmocrmClient struct {
|
||||
logger *logrus.Logger
|
||||
urls *models.AmocrmURL
|
||||
}
|
||||
|
||||
func NewAmocrmClient(deps *AmocrmClientDeps) *AmocrmClient {
|
||||
return &AmocrmClient{
|
||||
logger: deps.Logger,
|
||||
urls: deps.URLs,
|
||||
}
|
||||
}
|
||||
|
||||
func (receiver *AmocrmClient) GetUserInformation(ctx context.Context, accessToken string) (*models.AmocrmUserInformation, error) {
|
||||
response, err := client.Get[models.AmocrmUserInformation, any](ctx, &client.RequestSettings{
|
||||
URL: receiver.urls.UserInfo,
|
||||
Headers: map[string]string{
|
||||
"Authorization": fmt.Sprintf("Bearer %s", accessToken),
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to get user information on <GetUserInformation> of <AmocrmClient>: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response.Body, nil
|
||||
}
|
@ -5,10 +5,10 @@ import (
|
||||
"net/url"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/errors"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/utils"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/client"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/client"
|
||||
)
|
||||
|
||||
type AuthClientDeps struct {
|
||||
@ -49,42 +49,3 @@ func (receiver *AuthClient) GetUser(ctx context.Context, userID string) (*models
|
||||
|
||||
return response.Body, nil
|
||||
}
|
||||
|
||||
func (receiver *AuthClient) Register(ctx context.Context, request *models.RegisterRequest) (*models.Tokens, error) {
|
||||
response, err := client.Post[models.Tokens, models.FastifyError](ctx, &client.RequestSettings{
|
||||
URL: receiver.urls.Register,
|
||||
Headers: map[string]string{"Content-Type": "application/json"},
|
||||
Body: request,
|
||||
})
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to register user on <Register> of <AuthClient>: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
if response.Error != nil {
|
||||
receiver.logger.Errorf("failed request on <Register> of <AuthClient>: %s", response.Error.Message)
|
||||
return nil, utils.DetermineClientErrorResponse(response.StatusCode)
|
||||
}
|
||||
|
||||
return response.Body, nil
|
||||
}
|
||||
|
||||
func (receiver *AuthClient) Exchange(ctx context.Context, userID, signature string) (*models.Tokens, error) {
|
||||
response, err := client.Post[models.Tokens, models.FastifyError](ctx, &client.RequestSettings{
|
||||
URL: receiver.urls.Exchange,
|
||||
Headers: map[string]string{"Content-Type": "application/json"},
|
||||
Body: models.ExchangeRequest{
|
||||
UserID: userID,
|
||||
Signature: signature,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to exchange code on <Exchange> of <AuthClient>: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
if response.Error != nil {
|
||||
receiver.logger.Errorf("failed request on <Exchange> of <AuthClient>: %s", response.Error.Message)
|
||||
return nil, utils.DetermineClientErrorResponse(response.StatusCode)
|
||||
}
|
||||
|
||||
return response.Body, nil
|
||||
}
|
||||
|
@ -1,43 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/client"
|
||||
)
|
||||
|
||||
type GoogleClientDeps struct {
|
||||
Logger *logrus.Logger
|
||||
URLs *models.GoogleURL
|
||||
}
|
||||
|
||||
type GoogleClient struct {
|
||||
logger *logrus.Logger
|
||||
urls *models.GoogleURL
|
||||
}
|
||||
|
||||
func NewGoogleClient(deps *GoogleClientDeps) *GoogleClient {
|
||||
return &GoogleClient{
|
||||
logger: deps.Logger,
|
||||
urls: deps.URLs,
|
||||
}
|
||||
}
|
||||
|
||||
func (receiver *GoogleClient) GetUserInformation(ctx context.Context, accessToken string) (*models.GoogleUserInformation, error) {
|
||||
response, err := client.Get[models.GoogleUserInformation, any](ctx, &client.RequestSettings{
|
||||
URL: receiver.urls.UserInfo,
|
||||
Headers: map[string]string{
|
||||
"Authorization": fmt.Sprintf("Bearer %s", accessToken),
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to get user information on <GetUserInformation> of <GoogleClient>: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response.Body, nil
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/oauth2"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/utils"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/client"
|
||||
)
|
||||
|
||||
type OAuthClientDeps struct {
|
||||
Logger *logrus.Logger
|
||||
Config *oauth2.Config
|
||||
}
|
||||
|
||||
type OAuthClient struct {
|
||||
logger *logrus.Logger
|
||||
config *oauth2.Config
|
||||
}
|
||||
|
||||
func NewOAuthClient(deps *OAuthClientDeps) *OAuthClient {
|
||||
return &OAuthClient{
|
||||
logger: deps.Logger,
|
||||
config: deps.Config,
|
||||
}
|
||||
}
|
||||
|
||||
func (receiver *OAuthClient) Exchange(ctx context.Context, code string, options ...oauth2.AuthCodeOption) (*oauth2.Token, error) {
|
||||
if receiver.config.Endpoint.AuthStyle < 4 {
|
||||
return receiver.config.Exchange(ctx, code, options...)
|
||||
}
|
||||
|
||||
if receiver.config.Endpoint.AuthStyle == models.BodyAuthStyle {
|
||||
return receiver.bodyExchange(ctx, code)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (receiver *OAuthClient) AuthCodeURL(state string, options ...oauth2.AuthCodeOption) string {
|
||||
return receiver.config.AuthCodeURL(state, options...)
|
||||
}
|
||||
|
||||
func (receiver *OAuthClient) bodyExchange(ctx context.Context, code string) (*oauth2.Token, error) {
|
||||
response, err := client.Post[oauth2.Token, any](ctx, &client.RequestSettings{
|
||||
URL: receiver.config.Endpoint.TokenURL,
|
||||
Headers: map[string]string{"Content-Type": "application/json"},
|
||||
Body: map[string]string{
|
||||
"grant_type": "authorization_code",
|
||||
"redirect_uri": receiver.config.RedirectURL,
|
||||
"client_id": receiver.config.ClientID,
|
||||
"client_secret": receiver.config.ClientSecret,
|
||||
"code": code,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to exchange code on <bodyExchange> of <OAuthClient>: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
if response.Error != nil {
|
||||
receiver.logger.Errorf("failed request on <bodyExchange> of <OAuthClient>: %s", receiver.config.Endpoint.TokenURL)
|
||||
return nil, utils.DetermineClientErrorResponse(response.StatusCode)
|
||||
}
|
||||
|
||||
return response.Body, nil
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"github.com/SevereCloud/vksdk/v2/api"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/oauth2"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
)
|
||||
|
||||
type VKClient struct {
|
||||
logger *logrus.Logger
|
||||
}
|
||||
|
||||
func NewVKClient(logger *logrus.Logger) *VKClient {
|
||||
return &VKClient{logger: logger}
|
||||
}
|
||||
|
||||
func (receiver *VKClient) GetUserInformation(token *oauth2.Token) (*models.VKUserInformation, error) {
|
||||
vk := api.NewVK(token.AccessToken)
|
||||
userInformations := []models.VKUserInformation{}
|
||||
|
||||
if err := vk.RequestUnmarshal("users.get", &userInformations, api.Params{
|
||||
"fields": "id,photo_400_orig,sex,domain,screen_name,bdate,photo_id,followers_count,home_town,timezone,mobile_phone",
|
||||
}); err != nil {
|
||||
receiver.logger.Errorln("request error: ", err.Error())
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
currentUserInformation := userInformations[0]
|
||||
currentUserInformation.Email = token.Extra("email").(string)
|
||||
|
||||
return ¤tUserInformation, nil
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
package amocrm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/sirupsen/logrus"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/errors"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/utils"
|
||||
)
|
||||
|
||||
//go:generate mockery --name amocrmService
|
||||
type amocrmService interface {
|
||||
Auth(ctx context.Context, code string) (*models.Tokens, error)
|
||||
Link(ctx context.Context, code, accessToken string) (bool, error)
|
||||
}
|
||||
|
||||
//go:generate mockery --name oauthService
|
||||
type oauthService interface {
|
||||
GenerateAuthURL() string
|
||||
GenerateLinkURL(accessToken string) string
|
||||
ValidateState(state string) bool
|
||||
}
|
||||
|
||||
type Deps struct {
|
||||
Logger *logrus.Logger
|
||||
AmocrmService amocrmService
|
||||
OAuthService oauthService
|
||||
}
|
||||
|
||||
type Controller struct {
|
||||
logger *logrus.Logger
|
||||
amocrmService amocrmService
|
||||
oauthService oauthService
|
||||
}
|
||||
|
||||
func New(deps *Deps) *Controller {
|
||||
return &Controller{
|
||||
logger: deps.Logger,
|
||||
oauthService: deps.OAuthService,
|
||||
amocrmService: deps.AmocrmService,
|
||||
}
|
||||
}
|
||||
|
||||
func (receiver *Controller) RedirectAuthURL(ctx echo.Context) error {
|
||||
return ctx.Redirect(http.StatusTemporaryRedirect, receiver.oauthService.GenerateAuthURL())
|
||||
}
|
||||
|
||||
func (receiver *Controller) GenerateAuthURL(ctx echo.Context) error {
|
||||
return ctx.JSON(http.StatusOK, models.GenerateURLResponse{
|
||||
URL: receiver.oauthService.GenerateAuthURL(),
|
||||
})
|
||||
}
|
||||
|
||||
func (receiver *Controller) RedirectLinkAccountURL(ctx echo.Context) error {
|
||||
accessToken := ctx.QueryParam("accessToken")
|
||||
|
||||
return ctx.Redirect(http.StatusTemporaryRedirect, receiver.oauthService.GenerateLinkURL(accessToken))
|
||||
}
|
||||
|
||||
func (receiver *Controller) GenerateLinkAccountURL(ctx echo.Context) error {
|
||||
accessToken := ctx.QueryParam("accessToken")
|
||||
|
||||
return ctx.JSON(http.StatusOK, models.GenerateURLResponse{
|
||||
URL: receiver.oauthService.GenerateLinkURL(accessToken),
|
||||
})
|
||||
}
|
||||
|
||||
func (receiver *Controller) Callback(ctx echo.Context) error {
|
||||
callbackState := ctx.QueryParam("state")
|
||||
callbackCode := ctx.QueryParam("code")
|
||||
callbackAccessToken := ctx.QueryParam("accessToken")
|
||||
|
||||
if !receiver.oauthService.ValidateState(callbackState) {
|
||||
receiver.logger.Errorln("state is not valid on <Callback> of <AmocrmController>")
|
||||
return utils.DetermineEchoErrorResponse(ctx, errors.ErrInvalidArgs, "state is not valid")
|
||||
}
|
||||
|
||||
if callbackAccessToken != "" {
|
||||
tokens, err := receiver.amocrmService.Link(ctx.Request().Context(), callbackCode, callbackAccessToken)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to link amocrm account on <Callback> of <AmocrmAuthController>: %v", err)
|
||||
return utils.DetermineEchoErrorResponse(ctx, err, fmt.Sprintf("failed to link amocrm account: %v", err))
|
||||
}
|
||||
|
||||
return ctx.JSON(http.StatusOK, tokens)
|
||||
}
|
||||
|
||||
tokens, err := receiver.amocrmService.Auth(ctx.Request().Context(), callbackCode)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to amocrm auth on <Callback> of <AmocrmAuthController>: %v", err)
|
||||
return utils.DetermineEchoErrorResponse(ctx, err, fmt.Sprintf("failed to auth: %v", err))
|
||||
}
|
||||
|
||||
return ctx.JSON(http.StatusOK, tokens)
|
||||
}
|
@ -1,324 +0,0 @@
|
||||
package amocrm_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/controller/amocrm"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/controller/amocrm/mocks"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/json"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/testifyhelper"
|
||||
)
|
||||
|
||||
func TestAmocrmCallback(t *testing.T) {
|
||||
code := "testCode"
|
||||
accessToken := "accessttttoken"
|
||||
testifyHelper := testifyhelper.NewEchoTestifyHelper()
|
||||
|
||||
tokens := models.Tokens{
|
||||
AccessToken: "access-token",
|
||||
RefreshToken: "refresh-token",
|
||||
}
|
||||
|
||||
t.Run("Неверный state", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService(t)
|
||||
amocrmAuthController := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
OAuthService: oauthService,
|
||||
})
|
||||
|
||||
preparedRequest := testifyHelper.PrepareRequest(testifyhelper.RequestConfiguration{
|
||||
Method: http.MethodGet,
|
||||
Headers: map[string]string{echo.HeaderContentType: echo.MIMEApplicationJSON},
|
||||
QueryParams: map[string]string{
|
||||
"state": "invalid_state",
|
||||
"code": code,
|
||||
},
|
||||
})
|
||||
|
||||
oauthService.EXPECT().ValidateState("invalid_state").Return(false).Once()
|
||||
|
||||
assert.NoError(t, amocrmAuthController.Callback(preparedRequest.EchoContext))
|
||||
assert.Equal(t, http.StatusBadRequest, preparedRequest.Recorder.Code)
|
||||
})
|
||||
|
||||
t.Run("Сервис вернул ошибку (accessToken отсутствует)", func(t *testing.T) {
|
||||
amocrmService := mocks.NewAmocrmService(t)
|
||||
oauthService := mocks.NewOauthService(t)
|
||||
amocrmAuthController := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AmocrmService: amocrmService,
|
||||
OAuthService: oauthService,
|
||||
})
|
||||
|
||||
preparedRequest := testifyHelper.PrepareRequest(testifyhelper.RequestConfiguration{
|
||||
Method: http.MethodGet,
|
||||
Headers: map[string]string{echo.HeaderContentType: echo.MIMEApplicationJSON},
|
||||
QueryParams: map[string]string{
|
||||
"state": "random_state",
|
||||
"code": code,
|
||||
},
|
||||
})
|
||||
|
||||
oauthService.EXPECT().ValidateState("random_state").Return(true).Once()
|
||||
amocrmService.EXPECT().Auth(mock.Anything, code).Return(nil, errors.New("")).Once()
|
||||
|
||||
assert.NoError(t, amocrmAuthController.Callback(preparedRequest.EchoContext))
|
||||
assert.Equal(t, http.StatusInternalServerError, preparedRequest.Recorder.Code)
|
||||
})
|
||||
|
||||
t.Run("Сервис вернул ошибку (accessToken имеется)", func(t *testing.T) {
|
||||
amocrmService := mocks.NewAmocrmService(t)
|
||||
oauthService := mocks.NewOauthService(t)
|
||||
amocrmAuthController := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AmocrmService: amocrmService,
|
||||
OAuthService: oauthService,
|
||||
})
|
||||
|
||||
preparedRequest := testifyHelper.PrepareRequest(testifyhelper.RequestConfiguration{
|
||||
Method: http.MethodGet,
|
||||
Headers: map[string]string{echo.HeaderContentType: echo.MIMEApplicationJSON},
|
||||
QueryParams: map[string]string{
|
||||
"state": "state",
|
||||
"code": code,
|
||||
"accessToken": accessToken,
|
||||
},
|
||||
})
|
||||
|
||||
oauthService.EXPECT().ValidateState("state").Return(true).Once()
|
||||
amocrmService.AssertNotCalled(t, "Auth")
|
||||
amocrmService.EXPECT().Link(mock.Anything, code, accessToken).Return(false, errors.New("")).Once()
|
||||
|
||||
assert.NoError(t, amocrmAuthController.Callback(preparedRequest.EchoContext))
|
||||
assert.Equal(t, http.StatusInternalServerError, preparedRequest.Recorder.Code)
|
||||
})
|
||||
|
||||
t.Run("Сервис успешно отработал (accessToken отсутствует)", func(t *testing.T) {
|
||||
amocrmService := mocks.NewAmocrmService(t)
|
||||
oauthService := mocks.NewOauthService(t)
|
||||
amocrmAuthController := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AmocrmService: amocrmService,
|
||||
OAuthService: oauthService,
|
||||
})
|
||||
|
||||
jsonBuffer, err := json.EncodeBuffer(tokens)
|
||||
if err != nil {
|
||||
t.Errorf("failed to encode json tokens: %v", err)
|
||||
}
|
||||
|
||||
preparedRequest := testifyHelper.PrepareRequest(testifyhelper.RequestConfiguration{
|
||||
Method: http.MethodGet,
|
||||
Body: bytes.NewReader(jsonBuffer.Bytes()),
|
||||
Headers: map[string]string{echo.HeaderContentType: echo.MIMEApplicationJSON},
|
||||
QueryParams: map[string]string{
|
||||
"state": "some_state",
|
||||
"code": code,
|
||||
},
|
||||
})
|
||||
|
||||
oauthService.EXPECT().ValidateState("some_state").Return(true).Once()
|
||||
amocrmService.EXPECT().Auth(mock.Anything, code).Return(&tokens, nil).Once()
|
||||
|
||||
assert.NoError(t, amocrmAuthController.Callback(preparedRequest.EchoContext))
|
||||
assert.Equal(t, http.StatusOK, preparedRequest.Recorder.Code)
|
||||
})
|
||||
|
||||
t.Run("Сервис успешно отработал (accessToken имеется)", func(t *testing.T) {
|
||||
amocrmService := mocks.NewAmocrmService(t)
|
||||
oauthService := mocks.NewOauthService(t)
|
||||
amocrmAuthController := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AmocrmService: amocrmService,
|
||||
OAuthService: oauthService,
|
||||
})
|
||||
|
||||
jsonBuffer, err := json.EncodeBuffer(tokens)
|
||||
if err != nil {
|
||||
t.Errorf("failed to encode json tokens: %v", err)
|
||||
}
|
||||
|
||||
preparedRequest := testifyHelper.PrepareRequest(testifyhelper.RequestConfiguration{
|
||||
Method: http.MethodGet,
|
||||
Body: bytes.NewReader(jsonBuffer.Bytes()),
|
||||
Headers: map[string]string{echo.HeaderContentType: echo.MIMEApplicationJSON},
|
||||
QueryParams: map[string]string{
|
||||
"state": "login_state",
|
||||
"code": code,
|
||||
"accessToken": accessToken,
|
||||
},
|
||||
})
|
||||
|
||||
oauthService.EXPECT().ValidateState("login_state").Return(true).Once()
|
||||
amocrmService.AssertNotCalled(t, "Auth")
|
||||
amocrmService.EXPECT().Link(mock.Anything, code, accessToken).Return(true, nil).Once()
|
||||
|
||||
assert.NoError(t, amocrmAuthController.Callback(preparedRequest.EchoContext))
|
||||
assert.Equal(t, http.StatusOK, preparedRequest.Recorder.Code)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAmocrmGenerateAuthURL(t *testing.T) {
|
||||
testifyHelper := testifyhelper.NewEchoTestifyHelper()
|
||||
|
||||
t.Run("Успешная генерация ссылки авторизации", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService(t)
|
||||
amocrmAuthController := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
OAuthService: oauthService,
|
||||
})
|
||||
|
||||
preparedRequest := testifyHelper.PrepareRequest(testifyhelper.RequestConfiguration{
|
||||
Method: http.MethodGet,
|
||||
})
|
||||
|
||||
url := url.URL{
|
||||
Scheme: "https",
|
||||
Host: "www.amocrm.ru",
|
||||
Path: "/oauth",
|
||||
RawQuery: "access_type=offline&client_id=&response_type=code&state=555",
|
||||
}
|
||||
|
||||
oauthService.EXPECT().GenerateAuthURL().Return(url.String()).Once()
|
||||
|
||||
assert.NoError(t, amocrmAuthController.GenerateAuthURL(preparedRequest.EchoContext))
|
||||
|
||||
unmarsled, err := json.Unmarshal[models.GenerateURLResponse](preparedRequest.Recorder.Body.Bytes())
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, preparedRequest.Recorder.Code)
|
||||
assert.EqualValues(t, url.String(), unmarsled.URL)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAmocrmRedirectAuthURL(t *testing.T) {
|
||||
testifyHelper := testifyhelper.NewEchoTestifyHelper()
|
||||
|
||||
t.Run("Успешная генерация ссылки авторизации", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService(t)
|
||||
amocrmAuthController := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
OAuthService: oauthService,
|
||||
})
|
||||
|
||||
preparedRequest := testifyHelper.PrepareRequest(testifyhelper.RequestConfiguration{
|
||||
Method: http.MethodGet,
|
||||
})
|
||||
|
||||
url := url.URL{
|
||||
Scheme: "https",
|
||||
Host: "www.amocrm.ru",
|
||||
Path: "/oauth",
|
||||
RawQuery: "access_type=offline&client_id=&response_type=code&state=555",
|
||||
}
|
||||
|
||||
oauthService.EXPECT().GenerateAuthURL().Return(url.String()).Once()
|
||||
|
||||
assert.NoError(t, amocrmAuthController.RedirectAuthURL(preparedRequest.EchoContext))
|
||||
assert.Equal(t, http.StatusTemporaryRedirect, preparedRequest.Recorder.Code)
|
||||
|
||||
result := preparedRequest.Recorder.Result()
|
||||
if result != nil {
|
||||
defer result.Body.Close()
|
||||
}
|
||||
|
||||
if isNotNil := assert.NotNil(t, result); isNotNil {
|
||||
redirectURL, err := result.Location()
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, &url, redirectURL)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestAmocrmRedirectLinkAccountURL(t *testing.T) {
|
||||
testifyHelper := testifyhelper.NewEchoTestifyHelper()
|
||||
accessToken := "access-tokenasg"
|
||||
redirectURL := url.URL{
|
||||
Scheme: "https",
|
||||
Host: "www.amocrm.ru",
|
||||
Path: "/oauth",
|
||||
RawQuery: fmt.Sprintf(
|
||||
"accessToken=%s&access_type=offline&client_id=&response_type=code&state=555",
|
||||
accessToken,
|
||||
),
|
||||
}
|
||||
|
||||
t.Run("Успешная генерация ссылки авторизации с токеном доступа", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService(t)
|
||||
amocrmAuthController := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
OAuthService: oauthService,
|
||||
})
|
||||
|
||||
preparedRequest := testifyHelper.PrepareRequest(testifyhelper.RequestConfiguration{
|
||||
Method: http.MethodGet,
|
||||
QueryParams: map[string]string{"accessToken": accessToken},
|
||||
})
|
||||
|
||||
oauthService.EXPECT().GenerateLinkURL(accessToken).Return(redirectURL.String()).Once()
|
||||
|
||||
assert.NoError(t, amocrmAuthController.RedirectLinkAccountURL(preparedRequest.EchoContext))
|
||||
assert.Equal(t, http.StatusTemporaryRedirect, preparedRequest.Recorder.Code)
|
||||
|
||||
result := preparedRequest.Recorder.Result()
|
||||
if result != nil {
|
||||
defer result.Body.Close()
|
||||
}
|
||||
|
||||
if isNotNil := assert.NotNil(t, result); isNotNil {
|
||||
redirectURL, err := result.Location()
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, redirectURL, redirectURL)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestAmocrmGenerateLinkAccountURL(t *testing.T) {
|
||||
testifyHelper := testifyhelper.NewEchoTestifyHelper()
|
||||
accessToken := "access-token"
|
||||
redirectURL := url.URL{
|
||||
Scheme: "https",
|
||||
Host: "www.amocrm.ru",
|
||||
Path: "/oauth",
|
||||
RawQuery: fmt.Sprintf(
|
||||
"accessToken=%s&access_type=offline&client_id=&response_type=code&state=555",
|
||||
accessToken,
|
||||
),
|
||||
}
|
||||
|
||||
t.Run("Успешная генерация ссылки авторизации с токеном доступа", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService(t)
|
||||
amocrmAuthController := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
OAuthService: oauthService,
|
||||
})
|
||||
|
||||
preparedRequest := testifyHelper.PrepareRequest(testifyhelper.RequestConfiguration{
|
||||
Method: http.MethodGet,
|
||||
QueryParams: map[string]string{"accessToken": accessToken},
|
||||
})
|
||||
|
||||
oauthService.EXPECT().GenerateLinkURL(accessToken).Return(redirectURL.String()).Once()
|
||||
|
||||
assert.NoError(t, amocrmAuthController.GenerateLinkAccountURL(preparedRequest.EchoContext))
|
||||
assert.Equal(t, http.StatusOK, preparedRequest.Recorder.Code)
|
||||
|
||||
unmarsled, err := json.Unmarshal[models.GenerateURLResponse](preparedRequest.Recorder.Body.Bytes())
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, preparedRequest.Recorder.Code)
|
||||
assert.EqualValues(t, redirectURL.String(), unmarsled.URL)
|
||||
})
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
// Code generated by mockery v2.26.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
models "penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
)
|
||||
|
||||
// AmocrmService is an autogenerated mock type for the amocrmService type
|
||||
type AmocrmService struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type AmocrmService_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *AmocrmService) EXPECT() *AmocrmService_Expecter {
|
||||
return &AmocrmService_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// Auth provides a mock function with given fields: ctx, code
|
||||
func (_m *AmocrmService) Auth(ctx context.Context, code string) (*models.Tokens, error) {
|
||||
ret := _m.Called(ctx, code)
|
||||
|
||||
var r0 *models.Tokens
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*models.Tokens, error)); ok {
|
||||
return rf(ctx, code)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.Tokens); ok {
|
||||
r0 = rf(ctx, code)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Tokens)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, code)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AmocrmService_Auth_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Auth'
|
||||
type AmocrmService_Auth_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Auth is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - code string
|
||||
func (_e *AmocrmService_Expecter) Auth(ctx interface{}, code interface{}) *AmocrmService_Auth_Call {
|
||||
return &AmocrmService_Auth_Call{Call: _e.mock.On("Auth", ctx, code)}
|
||||
}
|
||||
|
||||
func (_c *AmocrmService_Auth_Call) Run(run func(ctx context.Context, code string)) *AmocrmService_Auth_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AmocrmService_Auth_Call) Return(_a0 *models.Tokens, _a1 error) *AmocrmService_Auth_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AmocrmService_Auth_Call) RunAndReturn(run func(context.Context, string) (*models.Tokens, error)) *AmocrmService_Auth_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Link provides a mock function with given fields: ctx, code, accessToken
|
||||
func (_m *AmocrmService) Link(ctx context.Context, code string, accessToken string) (bool, error) {
|
||||
ret := _m.Called(ctx, code, accessToken)
|
||||
|
||||
var r0 bool
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string) (bool, error)); ok {
|
||||
return rf(ctx, code, accessToken)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string) bool); ok {
|
||||
r0 = rf(ctx, code, accessToken)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
|
||||
r1 = rf(ctx, code, accessToken)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AmocrmService_Link_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Link'
|
||||
type AmocrmService_Link_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Link is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - code string
|
||||
// - accessToken string
|
||||
func (_e *AmocrmService_Expecter) Link(ctx interface{}, code interface{}, accessToken interface{}) *AmocrmService_Link_Call {
|
||||
return &AmocrmService_Link_Call{Call: _e.mock.On("Link", ctx, code, accessToken)}
|
||||
}
|
||||
|
||||
func (_c *AmocrmService_Link_Call) Run(run func(ctx context.Context, code string, accessToken string)) *AmocrmService_Link_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AmocrmService_Link_Call) Return(_a0 bool, _a1 error) *AmocrmService_Link_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AmocrmService_Link_Call) RunAndReturn(run func(context.Context, string, string) (bool, error)) *AmocrmService_Link_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewAmocrmService interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewAmocrmService creates a new instance of AmocrmService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewAmocrmService(t mockConstructorTestingTNewAmocrmService) *AmocrmService {
|
||||
mock := &AmocrmService{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
// Code generated by mockery v2.26.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import mock "github.com/stretchr/testify/mock"
|
||||
|
||||
// OauthService is an autogenerated mock type for the oauthService type
|
||||
type OauthService struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type OauthService_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *OauthService) EXPECT() *OauthService_Expecter {
|
||||
return &OauthService_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// GenerateAuthURL provides a mock function with given fields:
|
||||
func (_m *OauthService) GenerateAuthURL() string {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func() string); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// OauthService_GenerateAuthURL_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GenerateAuthURL'
|
||||
type OauthService_GenerateAuthURL_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GenerateAuthURL is a helper method to define mock.On call
|
||||
func (_e *OauthService_Expecter) GenerateAuthURL() *OauthService_GenerateAuthURL_Call {
|
||||
return &OauthService_GenerateAuthURL_Call{Call: _e.mock.On("GenerateAuthURL")}
|
||||
}
|
||||
|
||||
func (_c *OauthService_GenerateAuthURL_Call) Run(run func()) *OauthService_GenerateAuthURL_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *OauthService_GenerateAuthURL_Call) Return(_a0 string) *OauthService_GenerateAuthURL_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *OauthService_GenerateAuthURL_Call) RunAndReturn(run func() string) *OauthService_GenerateAuthURL_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GenerateLinkURL provides a mock function with given fields: accessToken
|
||||
func (_m *OauthService) GenerateLinkURL(accessToken string) string {
|
||||
ret := _m.Called(accessToken)
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func(string) string); ok {
|
||||
r0 = rf(accessToken)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// OauthService_GenerateLinkURL_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GenerateLinkURL'
|
||||
type OauthService_GenerateLinkURL_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GenerateLinkURL is a helper method to define mock.On call
|
||||
// - accessToken string
|
||||
func (_e *OauthService_Expecter) GenerateLinkURL(accessToken interface{}) *OauthService_GenerateLinkURL_Call {
|
||||
return &OauthService_GenerateLinkURL_Call{Call: _e.mock.On("GenerateLinkURL", accessToken)}
|
||||
}
|
||||
|
||||
func (_c *OauthService_GenerateLinkURL_Call) Run(run func(accessToken string)) *OauthService_GenerateLinkURL_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *OauthService_GenerateLinkURL_Call) Return(_a0 string) *OauthService_GenerateLinkURL_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *OauthService_GenerateLinkURL_Call) RunAndReturn(run func(string) string) *OauthService_GenerateLinkURL_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ValidateState provides a mock function with given fields: state
|
||||
func (_m *OauthService) ValidateState(state string) bool {
|
||||
ret := _m.Called(state)
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func(string) bool); ok {
|
||||
r0 = rf(state)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// OauthService_ValidateState_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ValidateState'
|
||||
type OauthService_ValidateState_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ValidateState is a helper method to define mock.On call
|
||||
// - state string
|
||||
func (_e *OauthService_Expecter) ValidateState(state interface{}) *OauthService_ValidateState_Call {
|
||||
return &OauthService_ValidateState_Call{Call: _e.mock.On("ValidateState", state)}
|
||||
}
|
||||
|
||||
func (_c *OauthService_ValidateState_Call) Run(run func(state string)) *OauthService_ValidateState_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *OauthService_ValidateState_Call) Return(_a0 bool) *OauthService_ValidateState_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *OauthService_ValidateState_Call) RunAndReturn(run func(string) bool) *OauthService_ValidateState_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewOauthService interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewOauthService creates a new instance of OauthService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewOauthService(t mockConstructorTestingTNewOauthService) *OauthService {
|
||||
mock := &OauthService{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
package google
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/oauth2"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/utils"
|
||||
)
|
||||
|
||||
// TODO:
|
||||
// 1) Необходимо вынести все ошибки в отдельный пакет
|
||||
// 2) Реализовать map'у для возврата JSON ошибок
|
||||
|
||||
type GoogleClient interface {
|
||||
GetUserInformation(ctx context.Context, accessToken string) (*models.GoogleUserInformation, error)
|
||||
}
|
||||
|
||||
type Deps struct {
|
||||
GoogleOAuthConfig *oauth2.Config
|
||||
Client GoogleClient
|
||||
Logger *logrus.Logger
|
||||
}
|
||||
|
||||
type Controller struct {
|
||||
oAuth *oauth2.Config
|
||||
logger *logrus.Logger
|
||||
client GoogleClient
|
||||
state string
|
||||
}
|
||||
|
||||
func New(deps *Deps) *Controller {
|
||||
return &Controller{
|
||||
oAuth: deps.GoogleOAuthConfig,
|
||||
logger: deps.Logger,
|
||||
client: deps.Client,
|
||||
state: utils.GetRandomString(10),
|
||||
}
|
||||
}
|
||||
|
||||
func (receiver *Controller) Auth(ctx echo.Context) error {
|
||||
url := receiver.oAuth.AuthCodeURL(receiver.state, oauth2.AccessTypeOffline)
|
||||
|
||||
return ctx.Redirect(http.StatusTemporaryRedirect, url)
|
||||
}
|
||||
|
||||
func (receiver *Controller) Callback(ctx echo.Context) error {
|
||||
callbackState := ctx.FormValue("state")
|
||||
callbackCode := ctx.FormValue("code")
|
||||
|
||||
if callbackState != receiver.state {
|
||||
receiver.logger.Errorln("state is not valid")
|
||||
|
||||
return ctx.JSON(http.StatusBadRequest, "state is not valid")
|
||||
}
|
||||
|
||||
token, err := receiver.oAuth.Exchange(ctx.Request().Context(), callbackCode)
|
||||
if err != nil {
|
||||
receiver.logger.Errorln("exchange error: ", err.Error())
|
||||
|
||||
return ctx.JSON(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
userInformation, err := receiver.client.GetUserInformation(ctx.Request().Context(), token.AccessToken)
|
||||
if err != nil {
|
||||
receiver.logger.Errorln("get user information error: ", err.Error())
|
||||
|
||||
return ctx.JSON(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return ctx.JSON(http.StatusOK, userInformation)
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
package vk
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/oauth2"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/utils"
|
||||
)
|
||||
|
||||
type VKClient interface {
|
||||
GetUserInformation(token *oauth2.Token) (*models.VKUserInformation, error)
|
||||
}
|
||||
|
||||
type Deps struct {
|
||||
VKOAuthConfig *oauth2.Config
|
||||
Client VKClient
|
||||
Logger *logrus.Logger
|
||||
}
|
||||
|
||||
type Controller struct {
|
||||
oAuth *oauth2.Config
|
||||
logger *logrus.Logger
|
||||
client VKClient
|
||||
state string
|
||||
}
|
||||
|
||||
func New(deps *Deps) *Controller {
|
||||
return &Controller{
|
||||
oAuth: deps.VKOAuthConfig,
|
||||
logger: deps.Logger,
|
||||
client: deps.Client,
|
||||
state: utils.GetRandomString(10),
|
||||
}
|
||||
}
|
||||
|
||||
func (receiver *Controller) Auth(ctx echo.Context) error {
|
||||
url := receiver.oAuth.AuthCodeURL(receiver.state, oauth2.AccessTypeOffline)
|
||||
|
||||
return ctx.Redirect(http.StatusTemporaryRedirect, url)
|
||||
}
|
||||
|
||||
func (receiver *Controller) Callback(ctx echo.Context) error {
|
||||
queries := ctx.Request().URL.Query()
|
||||
callbackCode := queries.Get("code")
|
||||
callbackState := queries.Get("state")
|
||||
|
||||
if callbackState != receiver.state {
|
||||
receiver.logger.Errorln("state is not valid on <Callback> of <AmocrmController>")
|
||||
|
||||
return ctx.JSON(http.StatusBadRequest, "state is not valid")
|
||||
}
|
||||
|
||||
token, err := receiver.oAuth.Exchange(ctx.Request().Context(), callbackCode)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("exchange error: %v", err)
|
||||
|
||||
return ctx.JSON(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
userInformation, err := receiver.client.GetUserInformation(token)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("get user information error: %v", err)
|
||||
|
||||
return ctx.JSON(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return ctx.JSON(http.StatusOK, userInformation)
|
||||
}
|
@ -3,8 +3,8 @@ package initialize
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/oauth2"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/client"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/client"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||
)
|
||||
|
||||
type ClientsDeps struct {
|
||||
@ -16,31 +16,14 @@ type ClientsDeps struct {
|
||||
}
|
||||
|
||||
type Clients struct {
|
||||
GoogleClient *client.GoogleClient
|
||||
VKClient *client.VKClient
|
||||
AmocrmClient *client.AmocrmClient
|
||||
AuthClient *client.AuthClient
|
||||
AmocrmOAuthClient *client.OAuthClient
|
||||
AuthClient *client.AuthClient
|
||||
}
|
||||
|
||||
func NewClients(deps *ClientsDeps) *Clients {
|
||||
return &Clients{
|
||||
VKClient: client.NewVKClient(deps.Logger),
|
||||
GoogleClient: client.NewGoogleClient(&client.GoogleClientDeps{
|
||||
Logger: deps.Logger,
|
||||
URLs: deps.GoogleURL,
|
||||
}),
|
||||
AmocrmClient: client.NewAmocrmClient(&client.AmocrmClientDeps{
|
||||
Logger: deps.Logger,
|
||||
URLs: deps.AmocrmURL,
|
||||
}),
|
||||
AuthClient: client.NewAuthClient(&client.AuthClientDeps{
|
||||
Logger: deps.Logger,
|
||||
URLs: deps.AuthURL,
|
||||
}),
|
||||
AmocrmOAuthClient: client.NewOAuthClient(&client.OAuthClientDeps{
|
||||
Logger: deps.Logger,
|
||||
Config: deps.AmocrmOAuthConfiguration,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/initialize"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
|
||||
)
|
||||
|
||||
func TestNewClients(t *testing.T) {
|
||||
@ -13,11 +13,7 @@ func TestNewClients(t *testing.T) {
|
||||
clients := initialize.NewClients(&initialize.ClientsDeps{})
|
||||
|
||||
assert.NotNil(t, clients)
|
||||
assert.NotNil(t, clients.AmocrmClient)
|
||||
assert.NotNil(t, clients.AuthClient)
|
||||
assert.NotNil(t, clients.GoogleClient)
|
||||
assert.NotNil(t, clients.AmocrmOAuthClient)
|
||||
assert.NotNil(t, clients.VKClient)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -7,9 +7,9 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
"golang.org/x/oauth2/vk"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/utils"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/env"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/env"
|
||||
)
|
||||
|
||||
func Configuration(path string) (*models.Config, error) {
|
||||
|
@ -9,9 +9,9 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
"golang.org/x/oauth2/vk"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/initialize"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/mongo"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/mongo"
|
||||
)
|
||||
|
||||
func setDefaultTestingENV(t *testing.T) *models.Config {
|
||||
|
@ -2,9 +2,6 @@ package initialize
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/controller/amocrm"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/controller/google"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/controller/vk"
|
||||
)
|
||||
|
||||
type ControllersDeps struct {
|
||||
@ -13,19 +10,8 @@ type ControllersDeps struct {
|
||||
}
|
||||
|
||||
type Controllers struct {
|
||||
GoogleController *google.Controller
|
||||
VKController *vk.Controller
|
||||
AmocrmController *amocrm.Controller
|
||||
}
|
||||
|
||||
func NewControllers(deps *ControllersDeps) *Controllers {
|
||||
return &Controllers{
|
||||
AmocrmController: amocrm.New(&amocrm.Deps{
|
||||
Logger: deps.Logger,
|
||||
OAuthService: deps.Services.AmocrmOAuthService,
|
||||
AmocrmService: deps.Services.AmocrmService,
|
||||
}),
|
||||
VKController: vk.New(&vk.Deps{}),
|
||||
GoogleController: google.New(&google.Deps{}),
|
||||
}
|
||||
return &Controllers{}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/initialize"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
|
||||
)
|
||||
|
||||
func TestNewControllers(t *testing.T) {
|
||||
@ -15,9 +15,6 @@ func TestNewControllers(t *testing.T) {
|
||||
})
|
||||
|
||||
assert.NotNil(t, controllers)
|
||||
assert.NotNil(t, controllers.AmocrmController)
|
||||
assert.NotNil(t, controllers.GoogleController)
|
||||
assert.NotNil(t, controllers.VKController)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package initialize
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/repository"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/repository"
|
||||
)
|
||||
|
||||
type RepositoriesDeps struct {
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.mongodb.org/mongo-driver/mongo/integration/mtest"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/initialize"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
|
||||
)
|
||||
|
||||
func TestNewRepositories(t *testing.T) {
|
||||
|
@ -2,12 +2,7 @@ package initialize
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/service/amocrm"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/service/auth"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/service/encrypt"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/service/oauth"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/utils"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||
)
|
||||
|
||||
type ServicesDeps struct {
|
||||
@ -18,34 +13,8 @@ type ServicesDeps struct {
|
||||
}
|
||||
|
||||
type Services struct {
|
||||
AmocrmService *amocrm.Service
|
||||
AmocrmOAuthService *oauth.Service[models.AmocrmUserInformation]
|
||||
}
|
||||
|
||||
func NewServices(deps *ServicesDeps) *Services {
|
||||
authService := auth.New(&auth.Deps{
|
||||
Logger: deps.Logger,
|
||||
AuthClient: deps.Clients.AuthClient,
|
||||
EncryptionService: encrypt.New(&encrypt.ServiceDeps{
|
||||
JWT: utils.NewJWT[models.JWTAuthUser](&deps.Config.JWT),
|
||||
PrivateCurveKey: deps.Config.AuthMicroservice.PrivateSignKey,
|
||||
SignSecret: deps.Config.AuthMicroservice.AuthGroup,
|
||||
}),
|
||||
})
|
||||
|
||||
amocrmOAuthService := oauth.New(&oauth.Deps[models.AmocrmUserInformation]{
|
||||
Logger: deps.Logger,
|
||||
ServiceClient: deps.Clients.AmocrmClient,
|
||||
OAuthClient: deps.Clients.AmocrmOAuthClient,
|
||||
})
|
||||
|
||||
return &Services{
|
||||
AmocrmOAuthService: amocrmOAuthService,
|
||||
AmocrmService: amocrm.New(&amocrm.Deps{
|
||||
Logger: deps.Logger,
|
||||
AuthService: authService,
|
||||
Repository: deps.Repositories.AmocrmRepository,
|
||||
OAuthService: amocrmOAuthService,
|
||||
}),
|
||||
}
|
||||
return &Services{}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/initialize"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
|
||||
)
|
||||
|
||||
func TestNewServices(t *testing.T) {
|
||||
@ -19,8 +19,6 @@ func TestNewServices(t *testing.T) {
|
||||
})
|
||||
|
||||
assert.NotNil(t, services)
|
||||
assert.NotNil(t, services.AmocrmOAuthService)
|
||||
assert.NotNil(t, services.AmocrmService)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"golang.org/x/oauth2"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/mongo"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/mongo"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
|
@ -8,10 +8,10 @@ import (
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/errors"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/fields"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
mongoWrapper "penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/mongo"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/fields"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||
mongoWrapper "penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/mongo"
|
||||
)
|
||||
|
||||
type AmocrmRepository struct {
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/errors"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||
)
|
||||
|
||||
type GoogleRepository struct {
|
||||
|
@ -6,11 +6,14 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
oapiMiddleware "github.com/deepmap/oapi-codegen/pkg/middleware"
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
"github.com/sirupsen/logrus"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/initialize"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/swagger"
|
||||
)
|
||||
|
||||
type HTTP struct {
|
||||
@ -19,11 +22,12 @@ type HTTP struct {
|
||||
echo *echo.Echo
|
||||
}
|
||||
|
||||
func New(logger *logrus.Logger) *HTTP {
|
||||
func New(logger *logrus.Logger, swagger *openapi3.T) *HTTP {
|
||||
echo := echo.New()
|
||||
|
||||
echo.Use(middleware.Logger())
|
||||
echo.Use(middleware.Recover())
|
||||
echo.Use(oapiMiddleware.OapiRequestValidator(swagger))
|
||||
|
||||
return &HTTP{
|
||||
echo: echo,
|
||||
@ -65,13 +69,7 @@ func (receiver *HTTP) Stop(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (receiver *HTTP) Register(controllers *initialize.Controllers) *HTTP {
|
||||
groupAmocrm := receiver.echo.Group("/amocrm")
|
||||
|
||||
groupAmocrm.GET("/auth/redirect", controllers.AmocrmController.RedirectAuthURL)
|
||||
groupAmocrm.GET("/auth", controllers.AmocrmController.GenerateAuthURL)
|
||||
groupAmocrm.GET("/link/redirect", controllers.AmocrmController.RedirectLinkAccountURL)
|
||||
groupAmocrm.GET("/link", controllers.AmocrmController.GenerateLinkAccountURL)
|
||||
groupAmocrm.GET("/callback", controllers.AmocrmController.Callback)
|
||||
swagger.RegisterHandlers(receiver.echo, nil)
|
||||
|
||||
return receiver
|
||||
}
|
||||
|
@ -1,131 +0,0 @@
|
||||
package amocrm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/errors"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
)
|
||||
|
||||
//go:generate mockery --name oauthService
|
||||
type oauthService[T models.AmocrmUserInformation] interface {
|
||||
GetUserInformationByCode(ctx context.Context, code string) (*T, error)
|
||||
}
|
||||
|
||||
//go:generate mockery --name authService
|
||||
type authService interface {
|
||||
Register(ctx context.Context, information *models.AuthUserInformation) (*models.Tokens, string, error)
|
||||
Login(ctx context.Context, userID string) (*models.Tokens, error)
|
||||
GetAuthUserByToken(ctx context.Context, accessToken string) (*models.AuthUser, error)
|
||||
}
|
||||
|
||||
//go:generate mockery --name amocrmRepository
|
||||
type amocrmRepository interface {
|
||||
FindByID(ctx context.Context, amocrmID string) (*models.AmocrmUser, error)
|
||||
FindByUserID(ctx context.Context, userID string) (*models.AmocrmUser, error)
|
||||
Insert(ctx context.Context, user *models.AmocrmUser) (*models.AmocrmUser, error)
|
||||
}
|
||||
|
||||
type Deps struct {
|
||||
Logger *logrus.Logger
|
||||
Repository amocrmRepository
|
||||
OAuthService oauthService[models.AmocrmUserInformation]
|
||||
AuthService authService
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
logger *logrus.Logger
|
||||
oauthService oauthService[models.AmocrmUserInformation]
|
||||
authService authService
|
||||
repository amocrmRepository
|
||||
}
|
||||
|
||||
func New(deps *Deps) *Service {
|
||||
return &Service{
|
||||
oauthService: deps.OAuthService,
|
||||
logger: deps.Logger,
|
||||
authService: deps.AuthService,
|
||||
repository: deps.Repository,
|
||||
}
|
||||
}
|
||||
|
||||
func (receiver *Service) Link(ctx context.Context, code, accessToken string) (bool, error) {
|
||||
authUser, err := receiver.authService.GetAuthUserByToken(ctx, accessToken)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to get auth user on <Link> of <AmocrmService>: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
amocrmUserInformation, err := receiver.oauthService.GetUserInformationByCode(ctx, code)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to get amocrm user information on <Link> of <AmocrmService>: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
amocrmUserID := strconv.Itoa(int(amocrmUserInformation.ID))
|
||||
|
||||
amocrmUser, err := receiver.repository.FindByID(ctx, amocrmUserID)
|
||||
if err != nil && err != errors.ErrNoRecord {
|
||||
receiver.logger.Errorf("failed to find user by amocrm id on <Link> of <AmocrmService>: %v", err)
|
||||
return false, err
|
||||
}
|
||||
if amocrmUser != nil {
|
||||
return false, errors.ErrRecordAlreadyExist
|
||||
}
|
||||
|
||||
if _, err := receiver.repository.Insert(ctx, &models.AmocrmUser{
|
||||
UserID: authUser.ID,
|
||||
AmocrmID: amocrmUserID,
|
||||
Information: *amocrmUserInformation,
|
||||
}); err != nil {
|
||||
receiver.logger.Errorf("failed to insert amocrm user on <Link> of <AmocrmService>: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (receiver *Service) Auth(ctx context.Context, code string) (*models.Tokens, error) {
|
||||
amocrmUserInformation, err := receiver.oauthService.GetUserInformationByCode(ctx, code)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to get amocrm user information on <Auth> of <AmocrmService>: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
amocrmUserID := strconv.Itoa(int(amocrmUserInformation.ID))
|
||||
|
||||
amocrmUser, err := receiver.repository.FindByID(ctx, amocrmUserID)
|
||||
if err != nil && err != errors.ErrNoRecord {
|
||||
receiver.logger.Errorf("failed to find amocrm user by id on <Auth> of <AmocrmService>: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if amocrmUser == nil {
|
||||
tokens, createdUserID, registerErr := receiver.authService.Register(ctx, &models.AuthUserInformation{})
|
||||
if registerErr != nil {
|
||||
receiver.logger.Errorf("failed to register amocrm user on <Auth> of <AmocrmService>: %v", err)
|
||||
return nil, registerErr
|
||||
}
|
||||
|
||||
if _, insertErr := receiver.repository.Insert(ctx, &models.AmocrmUser{
|
||||
UserID: createdUserID,
|
||||
AmocrmID: amocrmUserID,
|
||||
Information: *amocrmUserInformation,
|
||||
}); insertErr != nil {
|
||||
receiver.logger.Errorf("failed to insert user on <Auth> of <AmocrmService>: %v", err)
|
||||
return nil, insertErr
|
||||
}
|
||||
|
||||
return tokens, nil
|
||||
}
|
||||
|
||||
tokens, err := receiver.authService.Login(ctx, amocrmUser.UserID)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to login amocrm user on <Auth> of <AmocrmService>: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tokens, nil
|
||||
}
|
@ -1,522 +0,0 @@
|
||||
package amocrm_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/errors"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/service/amocrm"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/service/amocrm/mocks"
|
||||
)
|
||||
|
||||
var (
|
||||
inputCode = "input-code"
|
||||
|
||||
amocrmUserInformation = models.AmocrmUserInformation{
|
||||
ID: 2,
|
||||
UUID: "geagae0-13413g-gadg",
|
||||
}
|
||||
|
||||
amocrmUser = models.AmocrmUser{
|
||||
UserID: "153-35-5135",
|
||||
Information: amocrmUserInformation,
|
||||
}
|
||||
|
||||
authUser = models.AuthUser{
|
||||
ID: "1geat",
|
||||
Login: "gkohoeh",
|
||||
}
|
||||
|
||||
authTokens = models.Tokens{
|
||||
AccessToken: "auth-251-access-token-auth",
|
||||
RefreshToken: "auth-7582-refresh-token-auth",
|
||||
}
|
||||
)
|
||||
|
||||
func TestAmocrmLink(t *testing.T) {
|
||||
t.Run("Успешная привязка аккаунта amocrm", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService[models.AmocrmUserInformation](t)
|
||||
authService := mocks.NewAuthService(t)
|
||||
amocrmRepository := mocks.NewAmocrmRepository(t)
|
||||
amocrmService := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthService: authService,
|
||||
OAuthService: oauthService,
|
||||
Repository: amocrmRepository,
|
||||
})
|
||||
|
||||
getAuthUserCall := authService.EXPECT().
|
||||
GetAuthUserByToken(mock.Anything, authTokens.AccessToken).
|
||||
Return(&authUser, nil).
|
||||
Once()
|
||||
|
||||
getUserInformationCall := oauthService.EXPECT().
|
||||
GetUserInformationByCode(mock.Anything, inputCode).
|
||||
Return(&amocrmUserInformation, nil).
|
||||
Once()
|
||||
|
||||
findByAmocrmIDCall := amocrmRepository.EXPECT().
|
||||
FindByID(mock.Anything, strconv.Itoa(int(amocrmUserInformation.ID))).
|
||||
Return(nil, errors.ErrNoRecord).
|
||||
NotBefore(getUserInformationCall).
|
||||
Once()
|
||||
|
||||
amocrmRepository.EXPECT().
|
||||
Insert(mock.Anything, &models.AmocrmUser{
|
||||
UserID: authUser.ID,
|
||||
AmocrmID: strconv.Itoa(int(amocrmUserInformation.ID)),
|
||||
Information: amocrmUserInformation,
|
||||
}).
|
||||
Return(&amocrmUser, nil).
|
||||
NotBefore(getAuthUserCall, findByAmocrmIDCall).
|
||||
Once()
|
||||
|
||||
isLinked, err := amocrmService.Link(context.Background(), inputCode, authTokens.AccessToken)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, isLinked)
|
||||
})
|
||||
|
||||
t.Run("Ошибка получения пользователя ЕСА по токену при привязке аккаунта amocrm", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService[models.AmocrmUserInformation](t)
|
||||
authService := mocks.NewAuthService(t)
|
||||
amocrmRepository := mocks.NewAmocrmRepository(t)
|
||||
amocrmService := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthService: authService,
|
||||
OAuthService: oauthService,
|
||||
Repository: amocrmRepository,
|
||||
})
|
||||
|
||||
authService.EXPECT().
|
||||
GetAuthUserByToken(mock.Anything, authTokens.AccessToken).
|
||||
Return(&authUser, errors.ErrInvalidArgs).
|
||||
Once()
|
||||
|
||||
oauthService.AssertNotCalled(t, "GetUserInformationByCode")
|
||||
amocrmRepository.AssertNotCalled(t, "FindByID")
|
||||
amocrmRepository.AssertNotCalled(t, "Insert")
|
||||
|
||||
isLinked, err := amocrmService.Link(context.Background(), inputCode, authTokens.AccessToken)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrInvalidArgs.Error())
|
||||
assert.Equal(t, false, isLinked)
|
||||
})
|
||||
|
||||
t.Run("Ошибка получения пользователя amocrm по коду при привязке аккаунта amocrm", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService[models.AmocrmUserInformation](t)
|
||||
authService := mocks.NewAuthService(t)
|
||||
amocrmRepository := mocks.NewAmocrmRepository(t)
|
||||
amocrmService := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthService: authService,
|
||||
OAuthService: oauthService,
|
||||
Repository: amocrmRepository,
|
||||
})
|
||||
|
||||
authService.EXPECT().
|
||||
GetAuthUserByToken(mock.Anything, authTokens.AccessToken).
|
||||
Return(&authUser, nil).
|
||||
Once()
|
||||
|
||||
oauthService.EXPECT().
|
||||
GetUserInformationByCode(mock.Anything, inputCode).
|
||||
Return(nil, errors.ErrInvalidArgs).
|
||||
Once()
|
||||
|
||||
amocrmRepository.AssertNotCalled(t, "FindByID")
|
||||
amocrmRepository.AssertNotCalled(t, "Insert")
|
||||
|
||||
isLinked, err := amocrmService.Link(context.Background(), inputCode, authTokens.AccessToken)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrInvalidArgs.Error())
|
||||
assert.Equal(t, false, isLinked)
|
||||
})
|
||||
|
||||
t.Run("Ошибка привязки аккаунта amocrm: пользователь уже существует", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService[models.AmocrmUserInformation](t)
|
||||
authService := mocks.NewAuthService(t)
|
||||
amocrmRepository := mocks.NewAmocrmRepository(t)
|
||||
amocrmService := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthService: authService,
|
||||
OAuthService: oauthService,
|
||||
Repository: amocrmRepository,
|
||||
})
|
||||
|
||||
getAuthUserCall := authService.EXPECT().
|
||||
GetAuthUserByToken(mock.Anything, authTokens.AccessToken).
|
||||
Return(&authUser, nil).
|
||||
Once()
|
||||
|
||||
getUserInformationCall := oauthService.EXPECT().
|
||||
GetUserInformationByCode(mock.Anything, inputCode).
|
||||
Return(&amocrmUserInformation, nil).
|
||||
NotBefore(getAuthUserCall).
|
||||
Once()
|
||||
|
||||
amocrmRepository.EXPECT().
|
||||
FindByID(mock.Anything, strconv.Itoa(int(amocrmUserInformation.ID))).
|
||||
Return(&amocrmUser, nil).
|
||||
NotBefore(getUserInformationCall).
|
||||
Once()
|
||||
|
||||
amocrmRepository.AssertNotCalled(t, "Insert")
|
||||
|
||||
isLinked, err := amocrmService.Link(context.Background(), inputCode, authTokens.AccessToken)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrRecordAlreadyExist.Error())
|
||||
assert.Equal(t, false, isLinked)
|
||||
})
|
||||
|
||||
t.Run("Неизвестная ошибка при поиске пользователя amocrm в БД при привязке аккаунта", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService[models.AmocrmUserInformation](t)
|
||||
authService := mocks.NewAuthService(t)
|
||||
amocrmRepository := mocks.NewAmocrmRepository(t)
|
||||
amocrmService := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthService: authService,
|
||||
OAuthService: oauthService,
|
||||
Repository: amocrmRepository,
|
||||
})
|
||||
|
||||
authService.EXPECT().
|
||||
GetAuthUserByToken(mock.Anything, authTokens.AccessToken).
|
||||
Return(&authUser, nil).
|
||||
Once()
|
||||
|
||||
getUserInformationCall := oauthService.EXPECT().
|
||||
GetUserInformationByCode(mock.Anything, inputCode).
|
||||
Return(&amocrmUserInformation, nil).
|
||||
Once()
|
||||
|
||||
amocrmRepository.EXPECT().
|
||||
FindByID(mock.Anything, strconv.Itoa(int(amocrmUserInformation.ID))).
|
||||
Return(nil, errors.ErrDecodeRecord).
|
||||
NotBefore(getUserInformationCall).
|
||||
Once()
|
||||
|
||||
amocrmRepository.AssertNotCalled(t, "Insert")
|
||||
|
||||
isLinked, err := amocrmService.Link(context.Background(), inputCode, authTokens.AccessToken)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrDecodeRecord.Error())
|
||||
assert.Equal(t, false, isLinked)
|
||||
})
|
||||
|
||||
t.Run("Непредвиденная ошибка поиска пользователя amocrm при привязке аккаунта amocrm", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService[models.AmocrmUserInformation](t)
|
||||
authService := mocks.NewAuthService(t)
|
||||
amocrmRepository := mocks.NewAmocrmRepository(t)
|
||||
amocrmService := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthService: authService,
|
||||
OAuthService: oauthService,
|
||||
Repository: amocrmRepository,
|
||||
})
|
||||
|
||||
getAuthUserCall := authService.EXPECT().
|
||||
GetAuthUserByToken(mock.Anything, authTokens.AccessToken).
|
||||
Return(&authUser, nil).
|
||||
Once()
|
||||
|
||||
getUserInformationCall := oauthService.EXPECT().
|
||||
GetUserInformationByCode(mock.Anything, inputCode).
|
||||
Return(&amocrmUserInformation, nil).
|
||||
Once()
|
||||
|
||||
findByAmocrmIDCall := amocrmRepository.EXPECT().
|
||||
FindByID(mock.Anything, strconv.Itoa(int(amocrmUserInformation.ID))).
|
||||
Return(nil, errors.ErrNoRecord).
|
||||
NotBefore(getUserInformationCall).
|
||||
Once()
|
||||
|
||||
amocrmRepository.EXPECT().
|
||||
Insert(mock.Anything, &models.AmocrmUser{
|
||||
UserID: authUser.ID,
|
||||
AmocrmID: strconv.Itoa(int(amocrmUserInformation.ID)),
|
||||
Information: amocrmUserInformation,
|
||||
}).
|
||||
Return(nil, errors.ErrInsertRecord).
|
||||
NotBefore(getAuthUserCall, findByAmocrmIDCall).
|
||||
Once()
|
||||
|
||||
isLinked, err := amocrmService.Link(context.Background(), inputCode, authTokens.AccessToken)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrInsertRecord.Error())
|
||||
assert.Equal(t, false, isLinked)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAmocrmAuth(t *testing.T) {
|
||||
t.Run("Успешная авторизация аккаунта через amocrm (пользователь отсутствует в системе)", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService[models.AmocrmUserInformation](t)
|
||||
authService := mocks.NewAuthService(t)
|
||||
amocrmRepository := mocks.NewAmocrmRepository(t)
|
||||
amocrmService := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthService: authService,
|
||||
OAuthService: oauthService,
|
||||
Repository: amocrmRepository,
|
||||
})
|
||||
|
||||
getUserInfoByCodeCall := oauthService.EXPECT().
|
||||
GetUserInformationByCode(mock.Anything, inputCode).
|
||||
Return(&amocrmUserInformation, nil).
|
||||
Once()
|
||||
|
||||
findByIDCall := amocrmRepository.EXPECT().
|
||||
FindByID(mock.Anything, strconv.Itoa(int(amocrmUserInformation.ID))).
|
||||
Return(nil, errors.ErrNoRecord).
|
||||
NotBefore(getUserInfoByCodeCall).
|
||||
Once()
|
||||
|
||||
registerCall := authService.EXPECT().
|
||||
Register(mock.Anything, &models.AuthUserInformation{}).
|
||||
Return(&authTokens, authUser.ID, nil).
|
||||
NotBefore(findByIDCall).
|
||||
Once()
|
||||
|
||||
amocrmRepository.EXPECT().
|
||||
Insert(mock.Anything, &models.AmocrmUser{
|
||||
UserID: authUser.ID,
|
||||
AmocrmID: strconv.Itoa(int(amocrmUserInformation.ID)),
|
||||
Information: amocrmUserInformation,
|
||||
}).
|
||||
Return(&amocrmUser, nil).
|
||||
NotBefore(registerCall).
|
||||
Once()
|
||||
|
||||
authService.AssertNotCalled(t, "Login")
|
||||
|
||||
tokens, err := amocrmService.Auth(context.Background(), inputCode)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, &authTokens, tokens)
|
||||
})
|
||||
|
||||
t.Run("Успешная авторизация аккаунта через amocrm (пользователь присутствует в системе)", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService[models.AmocrmUserInformation](t)
|
||||
authService := mocks.NewAuthService(t)
|
||||
amocrmRepository := mocks.NewAmocrmRepository(t)
|
||||
amocrmService := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthService: authService,
|
||||
OAuthService: oauthService,
|
||||
Repository: amocrmRepository,
|
||||
})
|
||||
|
||||
getUserInfoByCodeCall := oauthService.EXPECT().
|
||||
GetUserInformationByCode(mock.Anything, inputCode).
|
||||
Return(&amocrmUserInformation, nil).
|
||||
Once()
|
||||
|
||||
findByIDCall := amocrmRepository.EXPECT().
|
||||
FindByID(mock.Anything, strconv.Itoa(int(amocrmUserInformation.ID))).
|
||||
Return(&amocrmUser, nil).
|
||||
NotBefore(getUserInfoByCodeCall).
|
||||
Once()
|
||||
|
||||
authService.EXPECT().
|
||||
Login(mock.Anything, amocrmUser.UserID).
|
||||
Return(&authTokens, nil).
|
||||
NotBefore(findByIDCall).
|
||||
Once()
|
||||
|
||||
authService.AssertNotCalled(t, "Register")
|
||||
|
||||
tokens, err := amocrmService.Auth(context.Background(), inputCode)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, &authTokens, tokens)
|
||||
})
|
||||
|
||||
t.Run("Ошибка логина при авторизации через amocrm (пользователь присутствует в системе)", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService[models.AmocrmUserInformation](t)
|
||||
authService := mocks.NewAuthService(t)
|
||||
amocrmRepository := mocks.NewAmocrmRepository(t)
|
||||
amocrmService := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthService: authService,
|
||||
OAuthService: oauthService,
|
||||
Repository: amocrmRepository,
|
||||
})
|
||||
|
||||
getUserInfoByCodeCall := oauthService.EXPECT().
|
||||
GetUserInformationByCode(mock.Anything, inputCode).
|
||||
Return(&amocrmUserInformation, nil).
|
||||
Once()
|
||||
|
||||
amocrmRepository.EXPECT().
|
||||
FindByID(mock.Anything, strconv.Itoa(int(amocrmUserInformation.ID))).
|
||||
Return(&amocrmUser, nil).
|
||||
NotBefore(getUserInfoByCodeCall).
|
||||
Once()
|
||||
|
||||
authService.EXPECT().
|
||||
Login(mock.Anything, amocrmUser.UserID).
|
||||
Return(nil, errors.ErrMethodNotImplemented).
|
||||
Once()
|
||||
|
||||
authService.AssertNotCalled(t, "Register")
|
||||
|
||||
tokens, err := amocrmService.Auth(context.Background(), inputCode)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrMethodNotImplemented.Error())
|
||||
assert.Nil(t, tokens)
|
||||
})
|
||||
|
||||
t.Run("Ошибка добавления пользователя amocrm в БД", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService[models.AmocrmUserInformation](t)
|
||||
authService := mocks.NewAuthService(t)
|
||||
amocrmRepository := mocks.NewAmocrmRepository(t)
|
||||
amocrmService := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthService: authService,
|
||||
OAuthService: oauthService,
|
||||
Repository: amocrmRepository,
|
||||
})
|
||||
|
||||
getUserInfoByCodeCall := oauthService.EXPECT().
|
||||
GetUserInformationByCode(mock.Anything, inputCode).
|
||||
Return(&amocrmUserInformation, nil).
|
||||
Once()
|
||||
|
||||
amocrmRepository.EXPECT().
|
||||
FindByID(mock.Anything, strconv.Itoa(int(amocrmUserInformation.ID))).
|
||||
Return(nil, errors.ErrNoRecord).
|
||||
NotBefore(getUserInfoByCodeCall).
|
||||
Once()
|
||||
|
||||
authService.EXPECT().
|
||||
Register(mock.Anything, &models.AuthUserInformation{}).
|
||||
Return(&authTokens, authUser.ID, nil).
|
||||
Once()
|
||||
|
||||
amocrmRepository.EXPECT().
|
||||
Insert(mock.Anything, &models.AmocrmUser{
|
||||
UserID: authUser.ID,
|
||||
AmocrmID: strconv.Itoa(int(amocrmUserInformation.ID)),
|
||||
Information: amocrmUserInformation,
|
||||
}).
|
||||
Return(nil, errors.ErrInsertRecord).
|
||||
Once()
|
||||
|
||||
authService.AssertNotCalled(t, "Login")
|
||||
|
||||
tokens, err := amocrmService.Auth(context.Background(), inputCode)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrInsertRecord.Error())
|
||||
assert.Nil(t, tokens)
|
||||
})
|
||||
|
||||
t.Run("Ошибка регистрации пользователя amocrm", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService[models.AmocrmUserInformation](t)
|
||||
authService := mocks.NewAuthService(t)
|
||||
amocrmRepository := mocks.NewAmocrmRepository(t)
|
||||
amocrmService := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthService: authService,
|
||||
OAuthService: oauthService,
|
||||
Repository: amocrmRepository,
|
||||
})
|
||||
|
||||
getUserInfoByCodeCall := oauthService.EXPECT().
|
||||
GetUserInformationByCode(mock.Anything, inputCode).
|
||||
Return(&amocrmUserInformation, nil).
|
||||
Once()
|
||||
|
||||
amocrmRepository.EXPECT().
|
||||
FindByID(mock.Anything, strconv.Itoa(int(amocrmUserInformation.ID))).
|
||||
Return(nil, errors.ErrNoRecord).
|
||||
NotBefore(getUserInfoByCodeCall).
|
||||
Once()
|
||||
|
||||
authService.EXPECT().
|
||||
Register(mock.Anything, &models.AuthUserInformation{}).
|
||||
Return(nil, "", errors.ErrMethodNotImplemented).
|
||||
Once()
|
||||
|
||||
amocrmRepository.AssertNotCalled(t, "Insert")
|
||||
authService.AssertNotCalled(t, "Login")
|
||||
|
||||
tokens, err := amocrmService.Auth(context.Background(), inputCode)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrMethodNotImplemented.Error())
|
||||
assert.Nil(t, tokens)
|
||||
})
|
||||
|
||||
t.Run("Ошибка получения пользователя amocrm при авторизации через аккаунт", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService[models.AmocrmUserInformation](t)
|
||||
authService := mocks.NewAuthService(t)
|
||||
amocrmRepository := mocks.NewAmocrmRepository(t)
|
||||
amocrmService := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthService: authService,
|
||||
OAuthService: oauthService,
|
||||
Repository: amocrmRepository,
|
||||
})
|
||||
|
||||
getUserInfoByCodeCall := oauthService.EXPECT().
|
||||
GetUserInformationByCode(mock.Anything, inputCode).
|
||||
Return(&amocrmUserInformation, nil).
|
||||
Once()
|
||||
|
||||
amocrmRepository.EXPECT().
|
||||
FindByID(mock.Anything, strconv.Itoa(int(amocrmUserInformation.ID))).
|
||||
Return(nil, errors.ErrFindRecord).
|
||||
NotBefore(getUserInfoByCodeCall).
|
||||
Once()
|
||||
|
||||
amocrmRepository.AssertNotCalled(t, "Insert")
|
||||
authService.AssertNotCalled(t, "Login")
|
||||
authService.AssertNotCalled(t, "Register")
|
||||
|
||||
tokens, err := amocrmService.Auth(context.Background(), inputCode)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrFindRecord.Error())
|
||||
assert.Nil(t, tokens)
|
||||
})
|
||||
|
||||
t.Run("Ошибка получения информации пользователя amocrm при авторизации через аккаунт", func(t *testing.T) {
|
||||
oauthService := mocks.NewOauthService[models.AmocrmUserInformation](t)
|
||||
authService := mocks.NewAuthService(t)
|
||||
amocrmRepository := mocks.NewAmocrmRepository(t)
|
||||
amocrmService := amocrm.New(&amocrm.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthService: authService,
|
||||
OAuthService: oauthService,
|
||||
Repository: amocrmRepository,
|
||||
})
|
||||
|
||||
oauthService.EXPECT().
|
||||
GetUserInformationByCode(mock.Anything, inputCode).
|
||||
Return(nil, errors.ErrMethodNotImplemented).
|
||||
Once()
|
||||
|
||||
amocrmRepository.AssertNotCalled(t, "Insert")
|
||||
amocrmRepository.AssertNotCalled(t, "FindByID")
|
||||
authService.AssertNotCalled(t, "Login")
|
||||
authService.AssertNotCalled(t, "Register")
|
||||
|
||||
tokens, err := amocrmService.Auth(context.Background(), inputCode)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrMethodNotImplemented.Error())
|
||||
assert.Nil(t, tokens)
|
||||
})
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
// Code generated by mockery v2.26.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
models "penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
)
|
||||
|
||||
// AmocrmRepository is an autogenerated mock type for the amocrmRepository type
|
||||
type AmocrmRepository struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type AmocrmRepository_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *AmocrmRepository) EXPECT() *AmocrmRepository_Expecter {
|
||||
return &AmocrmRepository_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// FindByID provides a mock function with given fields: ctx, amocrmID
|
||||
func (_m *AmocrmRepository) FindByID(ctx context.Context, amocrmID string) (*models.AmocrmUser, error) {
|
||||
ret := _m.Called(ctx, amocrmID)
|
||||
|
||||
var r0 *models.AmocrmUser
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*models.AmocrmUser, error)); ok {
|
||||
return rf(ctx, amocrmID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.AmocrmUser); ok {
|
||||
r0 = rf(ctx, amocrmID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.AmocrmUser)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, amocrmID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AmocrmRepository_FindByID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindByID'
|
||||
type AmocrmRepository_FindByID_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// FindByID is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - amocrmID string
|
||||
func (_e *AmocrmRepository_Expecter) FindByID(ctx interface{}, amocrmID interface{}) *AmocrmRepository_FindByID_Call {
|
||||
return &AmocrmRepository_FindByID_Call{Call: _e.mock.On("FindByID", ctx, amocrmID)}
|
||||
}
|
||||
|
||||
func (_c *AmocrmRepository_FindByID_Call) Run(run func(ctx context.Context, amocrmID string)) *AmocrmRepository_FindByID_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AmocrmRepository_FindByID_Call) Return(_a0 *models.AmocrmUser, _a1 error) *AmocrmRepository_FindByID_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AmocrmRepository_FindByID_Call) RunAndReturn(run func(context.Context, string) (*models.AmocrmUser, error)) *AmocrmRepository_FindByID_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// FindByUserID provides a mock function with given fields: ctx, userID
|
||||
func (_m *AmocrmRepository) FindByUserID(ctx context.Context, userID string) (*models.AmocrmUser, error) {
|
||||
ret := _m.Called(ctx, userID)
|
||||
|
||||
var r0 *models.AmocrmUser
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*models.AmocrmUser, error)); ok {
|
||||
return rf(ctx, userID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.AmocrmUser); ok {
|
||||
r0 = rf(ctx, userID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.AmocrmUser)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, userID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AmocrmRepository_FindByUserID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindByUserID'
|
||||
type AmocrmRepository_FindByUserID_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// FindByUserID is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - userID string
|
||||
func (_e *AmocrmRepository_Expecter) FindByUserID(ctx interface{}, userID interface{}) *AmocrmRepository_FindByUserID_Call {
|
||||
return &AmocrmRepository_FindByUserID_Call{Call: _e.mock.On("FindByUserID", ctx, userID)}
|
||||
}
|
||||
|
||||
func (_c *AmocrmRepository_FindByUserID_Call) Run(run func(ctx context.Context, userID string)) *AmocrmRepository_FindByUserID_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AmocrmRepository_FindByUserID_Call) Return(_a0 *models.AmocrmUser, _a1 error) *AmocrmRepository_FindByUserID_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AmocrmRepository_FindByUserID_Call) RunAndReturn(run func(context.Context, string) (*models.AmocrmUser, error)) *AmocrmRepository_FindByUserID_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Insert provides a mock function with given fields: ctx, user
|
||||
func (_m *AmocrmRepository) Insert(ctx context.Context, user *models.AmocrmUser) (*models.AmocrmUser, error) {
|
||||
ret := _m.Called(ctx, user)
|
||||
|
||||
var r0 *models.AmocrmUser
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.AmocrmUser) (*models.AmocrmUser, error)); ok {
|
||||
return rf(ctx, user)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.AmocrmUser) *models.AmocrmUser); ok {
|
||||
r0 = rf(ctx, user)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.AmocrmUser)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *models.AmocrmUser) error); ok {
|
||||
r1 = rf(ctx, user)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AmocrmRepository_Insert_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Insert'
|
||||
type AmocrmRepository_Insert_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Insert is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - user *models.AmocrmUser
|
||||
func (_e *AmocrmRepository_Expecter) Insert(ctx interface{}, user interface{}) *AmocrmRepository_Insert_Call {
|
||||
return &AmocrmRepository_Insert_Call{Call: _e.mock.On("Insert", ctx, user)}
|
||||
}
|
||||
|
||||
func (_c *AmocrmRepository_Insert_Call) Run(run func(ctx context.Context, user *models.AmocrmUser)) *AmocrmRepository_Insert_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*models.AmocrmUser))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AmocrmRepository_Insert_Call) Return(_a0 *models.AmocrmUser, _a1 error) *AmocrmRepository_Insert_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AmocrmRepository_Insert_Call) RunAndReturn(run func(context.Context, *models.AmocrmUser) (*models.AmocrmUser, error)) *AmocrmRepository_Insert_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewAmocrmRepository interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewAmocrmRepository creates a new instance of AmocrmRepository. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewAmocrmRepository(t mockConstructorTestingTNewAmocrmRepository) *AmocrmRepository {
|
||||
mock := &AmocrmRepository{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
@ -1,210 +0,0 @@
|
||||
// Code generated by mockery v2.26.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
models "penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
)
|
||||
|
||||
// AuthService is an autogenerated mock type for the authService type
|
||||
type AuthService struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type AuthService_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *AuthService) EXPECT() *AuthService_Expecter {
|
||||
return &AuthService_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// GetAuthUserByToken provides a mock function with given fields: ctx, accessToken
|
||||
func (_m *AuthService) GetAuthUserByToken(ctx context.Context, accessToken string) (*models.AuthUser, error) {
|
||||
ret := _m.Called(ctx, accessToken)
|
||||
|
||||
var r0 *models.AuthUser
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*models.AuthUser, error)); ok {
|
||||
return rf(ctx, accessToken)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.AuthUser); ok {
|
||||
r0 = rf(ctx, accessToken)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.AuthUser)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, accessToken)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AuthService_GetAuthUserByToken_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAuthUserByToken'
|
||||
type AuthService_GetAuthUserByToken_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetAuthUserByToken is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - accessToken string
|
||||
func (_e *AuthService_Expecter) GetAuthUserByToken(ctx interface{}, accessToken interface{}) *AuthService_GetAuthUserByToken_Call {
|
||||
return &AuthService_GetAuthUserByToken_Call{Call: _e.mock.On("GetAuthUserByToken", ctx, accessToken)}
|
||||
}
|
||||
|
||||
func (_c *AuthService_GetAuthUserByToken_Call) Run(run func(ctx context.Context, accessToken string)) *AuthService_GetAuthUserByToken_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AuthService_GetAuthUserByToken_Call) Return(_a0 *models.AuthUser, _a1 error) *AuthService_GetAuthUserByToken_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AuthService_GetAuthUserByToken_Call) RunAndReturn(run func(context.Context, string) (*models.AuthUser, error)) *AuthService_GetAuthUserByToken_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Login provides a mock function with given fields: ctx, userID
|
||||
func (_m *AuthService) Login(ctx context.Context, userID string) (*models.Tokens, error) {
|
||||
ret := _m.Called(ctx, userID)
|
||||
|
||||
var r0 *models.Tokens
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*models.Tokens, error)); ok {
|
||||
return rf(ctx, userID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.Tokens); ok {
|
||||
r0 = rf(ctx, userID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Tokens)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, userID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AuthService_Login_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Login'
|
||||
type AuthService_Login_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Login is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - userID string
|
||||
func (_e *AuthService_Expecter) Login(ctx interface{}, userID interface{}) *AuthService_Login_Call {
|
||||
return &AuthService_Login_Call{Call: _e.mock.On("Login", ctx, userID)}
|
||||
}
|
||||
|
||||
func (_c *AuthService_Login_Call) Run(run func(ctx context.Context, userID string)) *AuthService_Login_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AuthService_Login_Call) Return(_a0 *models.Tokens, _a1 error) *AuthService_Login_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AuthService_Login_Call) RunAndReturn(run func(context.Context, string) (*models.Tokens, error)) *AuthService_Login_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Register provides a mock function with given fields: ctx, information
|
||||
func (_m *AuthService) Register(ctx context.Context, information *models.AuthUserInformation) (*models.Tokens, string, error) {
|
||||
ret := _m.Called(ctx, information)
|
||||
|
||||
var r0 *models.Tokens
|
||||
var r1 string
|
||||
var r2 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.AuthUserInformation) (*models.Tokens, string, error)); ok {
|
||||
return rf(ctx, information)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.AuthUserInformation) *models.Tokens); ok {
|
||||
r0 = rf(ctx, information)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Tokens)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *models.AuthUserInformation) string); ok {
|
||||
r1 = rf(ctx, information)
|
||||
} else {
|
||||
r1 = ret.Get(1).(string)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(2).(func(context.Context, *models.AuthUserInformation) error); ok {
|
||||
r2 = rf(ctx, information)
|
||||
} else {
|
||||
r2 = ret.Error(2)
|
||||
}
|
||||
|
||||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// AuthService_Register_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Register'
|
||||
type AuthService_Register_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Register is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - information *models.AuthUserInformation
|
||||
func (_e *AuthService_Expecter) Register(ctx interface{}, information interface{}) *AuthService_Register_Call {
|
||||
return &AuthService_Register_Call{Call: _e.mock.On("Register", ctx, information)}
|
||||
}
|
||||
|
||||
func (_c *AuthService_Register_Call) Run(run func(ctx context.Context, information *models.AuthUserInformation)) *AuthService_Register_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*models.AuthUserInformation))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AuthService_Register_Call) Return(_a0 *models.Tokens, _a1 string, _a2 error) *AuthService_Register_Call {
|
||||
_c.Call.Return(_a0, _a1, _a2)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AuthService_Register_Call) RunAndReturn(run func(context.Context, *models.AuthUserInformation) (*models.Tokens, string, error)) *AuthService_Register_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewAuthService interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewAuthService creates a new instance of AuthService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewAuthService(t mockConstructorTestingTNewAuthService) *AuthService {
|
||||
mock := &AuthService{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
// Code generated by mockery v2.26.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// OauthService is an autogenerated mock type for the oauthService type
|
||||
type OauthService[T interface{}] struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type OauthService_Expecter[T interface{}] struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *OauthService[T]) EXPECT() *OauthService_Expecter[T] {
|
||||
return &OauthService_Expecter[T]{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// GetUserInformationByCode provides a mock function with given fields: ctx, code
|
||||
func (_m *OauthService[T]) GetUserInformationByCode(ctx context.Context, code string) (*T, error) {
|
||||
ret := _m.Called(ctx, code)
|
||||
|
||||
var r0 *T
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*T, error)); ok {
|
||||
return rf(ctx, code)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *T); ok {
|
||||
r0 = rf(ctx, code)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*T)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, code)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// OauthService_GetUserInformationByCode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetUserInformationByCode'
|
||||
type OauthService_GetUserInformationByCode_Call[T interface{}] struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetUserInformationByCode is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - code string
|
||||
func (_e *OauthService_Expecter[T]) GetUserInformationByCode(ctx interface{}, code interface{}) *OauthService_GetUserInformationByCode_Call[T] {
|
||||
return &OauthService_GetUserInformationByCode_Call[T]{Call: _e.mock.On("GetUserInformationByCode", ctx, code)}
|
||||
}
|
||||
|
||||
func (_c *OauthService_GetUserInformationByCode_Call[T]) Run(run func(ctx context.Context, code string)) *OauthService_GetUserInformationByCode_Call[T] {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *OauthService_GetUserInformationByCode_Call[T]) Return(_a0 *T, _a1 error) *OauthService_GetUserInformationByCode_Call[T] {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *OauthService_GetUserInformationByCode_Call[T]) RunAndReturn(run func(context.Context, string) (*T, error)) *OauthService_GetUserInformationByCode_Call[T] {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewOauthService interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewOauthService creates a new instance of OauthService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewOauthService[T interface{}](t mockConstructorTestingTNewOauthService) *OauthService[T] {
|
||||
mock := &OauthService[T]{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/utils"
|
||||
)
|
||||
|
||||
//go:generate mockery --name authClient
|
||||
type authClient interface {
|
||||
GetUser(ctx context.Context, userID string) (*models.AuthUser, error)
|
||||
Register(ctx context.Context, request *models.RegisterRequest) (*models.Tokens, error)
|
||||
Exchange(ctx context.Context, userID, signature string) (*models.Tokens, error)
|
||||
}
|
||||
|
||||
//go:generate mockery --name encryptionService
|
||||
type encryptionService interface {
|
||||
VerifyJWT(token string) (string, error)
|
||||
SignCommonSecret() ([]byte, error)
|
||||
}
|
||||
|
||||
type Deps struct {
|
||||
Logger *logrus.Logger
|
||||
AuthClient authClient
|
||||
EncryptionService encryptionService
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
logger *logrus.Logger
|
||||
authClient authClient
|
||||
encryptionService encryptionService
|
||||
}
|
||||
|
||||
func New(deps *Deps) *Service {
|
||||
return &Service{
|
||||
logger: deps.Logger,
|
||||
authClient: deps.AuthClient,
|
||||
encryptionService: deps.EncryptionService,
|
||||
}
|
||||
}
|
||||
|
||||
func (receiver *Service) Register(ctx context.Context, information *models.AuthUserInformation) (*models.Tokens, string, error) {
|
||||
tokens, err := receiver.authClient.Register(ctx, &models.RegisterRequest{
|
||||
Login: fmt.Sprintf("user_%d", time.Now().UnixNano()),
|
||||
PhoneNumber: information.PhoneNumber,
|
||||
Email: information.Email,
|
||||
Password: utils.GetRandomString(14),
|
||||
})
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to register user on <Register> of <AuthService>: %v", err)
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
userID, err := receiver.encryptionService.VerifyJWT(tokens.AccessToken)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to verify jwt on <Register> of <AuthService>: %v", err)
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
return tokens, userID, nil
|
||||
}
|
||||
|
||||
func (receiver *Service) Login(ctx context.Context, userID string) (*models.Tokens, error) {
|
||||
signature, err := receiver.encryptionService.SignCommonSecret()
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to sign common secret on <Login> of <AuthService>: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tokens, err := receiver.authClient.Exchange(ctx, userID, string(signature))
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to exchange code on <Login> of <AuthService>: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tokens, nil
|
||||
}
|
||||
|
||||
func (receiver *Service) GetAuthUserByToken(ctx context.Context, accessToken string) (*models.AuthUser, error) {
|
||||
userID, err := receiver.encryptionService.VerifyJWT(accessToken)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to vetify jwt on <GetAuthUserByToken> of <AuthService>: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user, err := receiver.authClient.GetUser(ctx, userID)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to get user on <GetAuthUserByToken> of <AuthService>: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
@ -1,288 +0,0 @@
|
||||
package auth_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/errors"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/service/auth"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/service/auth/mocks"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/validate"
|
||||
)
|
||||
|
||||
var (
|
||||
userID = "user-id-14"
|
||||
|
||||
authUserInformation = models.AuthUserInformation{
|
||||
PhoneNumber: "+75819369631",
|
||||
Email: "test@mail.ru",
|
||||
}
|
||||
|
||||
authTokens = models.Tokens{
|
||||
AccessToken: "access-token-auth",
|
||||
RefreshToken: "refresh-token-auth",
|
||||
}
|
||||
|
||||
authUser = models.AuthUser{
|
||||
ID: "1geat",
|
||||
Login: "gkohoeh",
|
||||
PhoneNumber: authUserInformation.PhoneNumber,
|
||||
Email: authUserInformation.Email,
|
||||
}
|
||||
|
||||
validateRegisterRequest = mock.MatchedBy(func(request *models.RegisterRequest) bool {
|
||||
isLoginFilled := !validate.IsStringEmpty(request.Login)
|
||||
isPasswordFilled := !validate.IsStringEmpty(request.Password)
|
||||
isEmailFilled := request.Email == authUserInformation.Email
|
||||
isPhoneFilled := request.PhoneNumber == authUserInformation.PhoneNumber
|
||||
|
||||
if isLoginFilled && isPasswordFilled && isEmailFilled && isPhoneFilled {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
)
|
||||
|
||||
func TestAuthRegister(t *testing.T) {
|
||||
t.Run("Успешная регистарция пользователя", func(t *testing.T) {
|
||||
authClient := mocks.NewAuthClient(t)
|
||||
encryptionService := mocks.NewEncryptionService(t)
|
||||
authService := auth.New(&auth.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthClient: authClient,
|
||||
EncryptionService: encryptionService,
|
||||
})
|
||||
|
||||
registerAuthUserCall := authClient.EXPECT().
|
||||
Register(mock.Anything, validateRegisterRequest).
|
||||
Return(&authTokens, nil).
|
||||
Once()
|
||||
|
||||
encryptionService.EXPECT().
|
||||
VerifyJWT(authTokens.AccessToken).
|
||||
Return(userID, nil).
|
||||
NotBefore(registerAuthUserCall).
|
||||
Once()
|
||||
|
||||
registrationTokens, registeredUserID, err := authService.Register(context.Background(), &authUserInformation)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, &authTokens, registrationTokens)
|
||||
assert.Equal(t, userID, registeredUserID)
|
||||
})
|
||||
|
||||
t.Run("Ошибка регистрации пользователя в auth микросервисе при регистрации", func(t *testing.T) {
|
||||
authClient := mocks.NewAuthClient(t)
|
||||
encryptionService := mocks.NewEncryptionService(t)
|
||||
authService := auth.New(&auth.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthClient: authClient,
|
||||
EncryptionService: encryptionService,
|
||||
})
|
||||
|
||||
authClient.EXPECT().
|
||||
Register(mock.Anything, validateRegisterRequest).
|
||||
Return(nil, errors.ErrMethodNotImplemented).
|
||||
Once()
|
||||
|
||||
encryptionService.AssertNotCalled(t, "VerifyJWT")
|
||||
|
||||
registrationTokens, registeredUserID, err := authService.Register(context.Background(), &authUserInformation)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrMethodNotImplemented.Error())
|
||||
assert.Nil(t, registrationTokens)
|
||||
assert.Empty(t, registeredUserID)
|
||||
})
|
||||
|
||||
t.Run("Ошибка подтверждения токена единой системы авторизации при регистрации", func(t *testing.T) {
|
||||
authClient := mocks.NewAuthClient(t)
|
||||
encryptionService := mocks.NewEncryptionService(t)
|
||||
authService := auth.New(&auth.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthClient: authClient,
|
||||
EncryptionService: encryptionService,
|
||||
})
|
||||
|
||||
registerAuthUserCall := authClient.EXPECT().
|
||||
Register(mock.Anything, validateRegisterRequest).
|
||||
Return(&authTokens, nil).
|
||||
Once()
|
||||
|
||||
encryptionService.EXPECT().
|
||||
VerifyJWT(authTokens.AccessToken).
|
||||
Return("", errors.ErrInvalidArgs).
|
||||
NotBefore(registerAuthUserCall).
|
||||
Once()
|
||||
|
||||
registrationTokens, registeredUserID, err := authService.Register(context.Background(), &authUserInformation)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrInvalidArgs.Error())
|
||||
assert.Nil(t, registrationTokens)
|
||||
assert.Empty(t, registeredUserID)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthLogin(t *testing.T) {
|
||||
t.Run("Успешная авторизация пользователя", func(t *testing.T) {
|
||||
authClient := mocks.NewAuthClient(t)
|
||||
encryptionService := mocks.NewEncryptionService(t)
|
||||
authService := auth.New(&auth.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthClient: authClient,
|
||||
EncryptionService: encryptionService,
|
||||
})
|
||||
|
||||
encryptCodeCall := encryptionService.EXPECT().
|
||||
SignCommonSecret().
|
||||
Return([]byte{116, 116}, nil).
|
||||
Once()
|
||||
|
||||
authClient.EXPECT().
|
||||
Exchange(mock.Anything, userID, "tt").
|
||||
Return(&authTokens, nil).
|
||||
NotBefore(encryptCodeCall).
|
||||
Once()
|
||||
|
||||
loginTokens, err := authService.Login(context.Background(), userID)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, &authTokens, loginTokens)
|
||||
})
|
||||
|
||||
t.Run("Ошибка шифрования кода обмена при авторизации", func(t *testing.T) {
|
||||
authClient := mocks.NewAuthClient(t)
|
||||
encryptionService := mocks.NewEncryptionService(t)
|
||||
authService := auth.New(&auth.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthClient: authClient,
|
||||
EncryptionService: encryptionService,
|
||||
})
|
||||
|
||||
encryptionService.EXPECT().
|
||||
SignCommonSecret().
|
||||
Return([]byte{111, 116}, errors.ErrInvalidArgs).
|
||||
Once()
|
||||
|
||||
authClient.AssertNotCalled(t, "Exchange")
|
||||
|
||||
loginTokens, err := authService.Login(context.Background(), userID)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrInvalidArgs.Error())
|
||||
assert.Nil(t, loginTokens)
|
||||
})
|
||||
|
||||
t.Run("Ошибка обмена зашифрованного кода на токены при авторизации", func(t *testing.T) {
|
||||
authClient := mocks.NewAuthClient(t)
|
||||
encryptionService := mocks.NewEncryptionService(t)
|
||||
authService := auth.New(&auth.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthClient: authClient,
|
||||
EncryptionService: encryptionService,
|
||||
})
|
||||
|
||||
encryptCodeCall := encryptionService.EXPECT().
|
||||
SignCommonSecret().
|
||||
Return([]byte{97, 97}, nil).
|
||||
Once()
|
||||
|
||||
authClient.EXPECT().
|
||||
Exchange(mock.Anything, userID, "aa").
|
||||
Return(nil, errors.ErrMethodNotImplemented).
|
||||
NotBefore(encryptCodeCall).
|
||||
Once()
|
||||
|
||||
loginTokens, err := authService.Login(context.Background(), userID)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrMethodNotImplemented.Error())
|
||||
assert.Nil(t, loginTokens)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetAuthUserByToken(t *testing.T) {
|
||||
t.Run("Успешное получение информации о пользователе ЕСА через токен", func(t *testing.T) {
|
||||
authClient := mocks.NewAuthClient(t)
|
||||
encryptionService := mocks.NewEncryptionService(t)
|
||||
authService := auth.New(&auth.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthClient: authClient,
|
||||
EncryptionService: encryptionService,
|
||||
})
|
||||
|
||||
encryptCodeCall := encryptionService.EXPECT().
|
||||
VerifyJWT(authTokens.AccessToken).
|
||||
Return(userID, nil).
|
||||
Once()
|
||||
|
||||
authClient.EXPECT().
|
||||
GetUser(mock.Anything, userID).
|
||||
Return(&authUser, nil).
|
||||
NotBefore(encryptCodeCall).
|
||||
Once()
|
||||
|
||||
user, err := authService.GetAuthUserByToken(context.Background(), authTokens.AccessToken)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, &authUser, user)
|
||||
})
|
||||
|
||||
t.Run("Ошибка запроса получения пользователя ЕСА", func(t *testing.T) {
|
||||
authClient := mocks.NewAuthClient(t)
|
||||
encryptionService := mocks.NewEncryptionService(t)
|
||||
authService := auth.New(&auth.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthClient: authClient,
|
||||
EncryptionService: encryptionService,
|
||||
})
|
||||
|
||||
encryptCodeCall := encryptionService.EXPECT().
|
||||
VerifyJWT(authTokens.AccessToken).
|
||||
Return(userID, nil).
|
||||
Once()
|
||||
|
||||
authClient.EXPECT().
|
||||
GetUser(mock.Anything, userID).
|
||||
Return(&authUser, errors.ErrMethodNotImplemented).
|
||||
NotBefore(encryptCodeCall).
|
||||
Once()
|
||||
|
||||
user, err := authService.GetAuthUserByToken(context.Background(), authTokens.AccessToken)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.NotNil(t, err)
|
||||
assert.EqualError(t, err, errors.ErrMethodNotImplemented.Error())
|
||||
assert.Nil(t, user)
|
||||
})
|
||||
|
||||
t.Run("Ошибка подтверждения токена при получении пользователя ЕСА по токену", func(t *testing.T) {
|
||||
authClient := mocks.NewAuthClient(t)
|
||||
encryptionService := mocks.NewEncryptionService(t)
|
||||
authService := auth.New(&auth.Deps{
|
||||
Logger: logrus.New(),
|
||||
AuthClient: authClient,
|
||||
EncryptionService: encryptionService,
|
||||
})
|
||||
|
||||
encryptionService.EXPECT().
|
||||
VerifyJWT(authTokens.AccessToken).
|
||||
Return("", errors.ErrEmptyArgs).
|
||||
Once()
|
||||
|
||||
authClient.AssertNotCalled(t, "GetUser")
|
||||
|
||||
user, err := authService.GetAuthUserByToken(context.Background(), authTokens.AccessToken)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.NotNil(t, err)
|
||||
assert.EqualError(t, err, errors.ErrEmptyArgs.Error())
|
||||
assert.Nil(t, user)
|
||||
})
|
||||
}
|
@ -1,204 +0,0 @@
|
||||
// Code generated by mockery v2.26.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
models "penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
)
|
||||
|
||||
// AuthClient is an autogenerated mock type for the authClient type
|
||||
type AuthClient struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type AuthClient_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *AuthClient) EXPECT() *AuthClient_Expecter {
|
||||
return &AuthClient_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// Exchange provides a mock function with given fields: ctx, userID, signature
|
||||
func (_m *AuthClient) Exchange(ctx context.Context, userID string, signature string) (*models.Tokens, error) {
|
||||
ret := _m.Called(ctx, userID, signature)
|
||||
|
||||
var r0 *models.Tokens
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string) (*models.Tokens, error)); ok {
|
||||
return rf(ctx, userID, signature)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string) *models.Tokens); ok {
|
||||
r0 = rf(ctx, userID, signature)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Tokens)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
|
||||
r1 = rf(ctx, userID, signature)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AuthClient_Exchange_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Exchange'
|
||||
type AuthClient_Exchange_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Exchange is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - userID string
|
||||
// - signature string
|
||||
func (_e *AuthClient_Expecter) Exchange(ctx interface{}, userID interface{}, signature interface{}) *AuthClient_Exchange_Call {
|
||||
return &AuthClient_Exchange_Call{Call: _e.mock.On("Exchange", ctx, userID, signature)}
|
||||
}
|
||||
|
||||
func (_c *AuthClient_Exchange_Call) Run(run func(ctx context.Context, userID string, signature string)) *AuthClient_Exchange_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AuthClient_Exchange_Call) Return(_a0 *models.Tokens, _a1 error) *AuthClient_Exchange_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AuthClient_Exchange_Call) RunAndReturn(run func(context.Context, string, string) (*models.Tokens, error)) *AuthClient_Exchange_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetUser provides a mock function with given fields: ctx, userID
|
||||
func (_m *AuthClient) GetUser(ctx context.Context, userID string) (*models.AuthUser, error) {
|
||||
ret := _m.Called(ctx, userID)
|
||||
|
||||
var r0 *models.AuthUser
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*models.AuthUser, error)); ok {
|
||||
return rf(ctx, userID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.AuthUser); ok {
|
||||
r0 = rf(ctx, userID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.AuthUser)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, userID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AuthClient_GetUser_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetUser'
|
||||
type AuthClient_GetUser_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetUser is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - userID string
|
||||
func (_e *AuthClient_Expecter) GetUser(ctx interface{}, userID interface{}) *AuthClient_GetUser_Call {
|
||||
return &AuthClient_GetUser_Call{Call: _e.mock.On("GetUser", ctx, userID)}
|
||||
}
|
||||
|
||||
func (_c *AuthClient_GetUser_Call) Run(run func(ctx context.Context, userID string)) *AuthClient_GetUser_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AuthClient_GetUser_Call) Return(_a0 *models.AuthUser, _a1 error) *AuthClient_GetUser_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AuthClient_GetUser_Call) RunAndReturn(run func(context.Context, string) (*models.AuthUser, error)) *AuthClient_GetUser_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Register provides a mock function with given fields: ctx, request
|
||||
func (_m *AuthClient) Register(ctx context.Context, request *models.RegisterRequest) (*models.Tokens, error) {
|
||||
ret := _m.Called(ctx, request)
|
||||
|
||||
var r0 *models.Tokens
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.RegisterRequest) (*models.Tokens, error)); ok {
|
||||
return rf(ctx, request)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.RegisterRequest) *models.Tokens); ok {
|
||||
r0 = rf(ctx, request)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Tokens)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *models.RegisterRequest) error); ok {
|
||||
r1 = rf(ctx, request)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AuthClient_Register_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Register'
|
||||
type AuthClient_Register_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Register is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - request *models.RegisterRequest
|
||||
func (_e *AuthClient_Expecter) Register(ctx interface{}, request interface{}) *AuthClient_Register_Call {
|
||||
return &AuthClient_Register_Call{Call: _e.mock.On("Register", ctx, request)}
|
||||
}
|
||||
|
||||
func (_c *AuthClient_Register_Call) Run(run func(ctx context.Context, request *models.RegisterRequest)) *AuthClient_Register_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*models.RegisterRequest))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AuthClient_Register_Call) Return(_a0 *models.Tokens, _a1 error) *AuthClient_Register_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AuthClient_Register_Call) RunAndReturn(run func(context.Context, *models.RegisterRequest) (*models.Tokens, error)) *AuthClient_Register_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewAuthClient interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewAuthClient creates a new instance of AuthClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewAuthClient(t mockConstructorTestingTNewAuthClient) *AuthClient {
|
||||
mock := &AuthClient{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
@ -1,138 +0,0 @@
|
||||
// Code generated by mockery v2.26.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import mock "github.com/stretchr/testify/mock"
|
||||
|
||||
// EncryptionService is an autogenerated mock type for the encryptionService type
|
||||
type EncryptionService struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type EncryptionService_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *EncryptionService) EXPECT() *EncryptionService_Expecter {
|
||||
return &EncryptionService_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// SignCommonSecret provides a mock function with given fields:
|
||||
func (_m *EncryptionService) SignCommonSecret() ([]byte, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 []byte
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func() ([]byte, error)); ok {
|
||||
return rf()
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func() []byte); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]byte)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func() error); ok {
|
||||
r1 = rf()
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// EncryptionService_SignCommonSecret_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SignCommonSecret'
|
||||
type EncryptionService_SignCommonSecret_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// SignCommonSecret is a helper method to define mock.On call
|
||||
func (_e *EncryptionService_Expecter) SignCommonSecret() *EncryptionService_SignCommonSecret_Call {
|
||||
return &EncryptionService_SignCommonSecret_Call{Call: _e.mock.On("SignCommonSecret")}
|
||||
}
|
||||
|
||||
func (_c *EncryptionService_SignCommonSecret_Call) Run(run func()) *EncryptionService_SignCommonSecret_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *EncryptionService_SignCommonSecret_Call) Return(_a0 []byte, _a1 error) *EncryptionService_SignCommonSecret_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *EncryptionService_SignCommonSecret_Call) RunAndReturn(run func() ([]byte, error)) *EncryptionService_SignCommonSecret_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// VerifyJWT provides a mock function with given fields: token
|
||||
func (_m *EncryptionService) VerifyJWT(token string) (string, error) {
|
||||
ret := _m.Called(token)
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string) (string, error)); ok {
|
||||
return rf(token)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string) string); ok {
|
||||
r0 = rf(token)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(token)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// EncryptionService_VerifyJWT_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'VerifyJWT'
|
||||
type EncryptionService_VerifyJWT_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// VerifyJWT is a helper method to define mock.On call
|
||||
// - token string
|
||||
func (_e *EncryptionService_Expecter) VerifyJWT(token interface{}) *EncryptionService_VerifyJWT_Call {
|
||||
return &EncryptionService_VerifyJWT_Call{Call: _e.mock.On("VerifyJWT", token)}
|
||||
}
|
||||
|
||||
func (_c *EncryptionService_VerifyJWT_Call) Run(run func(token string)) *EncryptionService_VerifyJWT_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *EncryptionService_VerifyJWT_Call) Return(_a0 string, _a1 error) *EncryptionService_VerifyJWT_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *EncryptionService_VerifyJWT_Call) RunAndReturn(run func(string) (string, error)) *EncryptionService_VerifyJWT_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewEncryptionService interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewEncryptionService creates a new instance of EncryptionService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewEncryptionService(t mockConstructorTestingTNewEncryptionService) *EncryptionService {
|
||||
mock := &EncryptionService{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
package encrypt
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
)
|
||||
|
||||
//go:generate mockery --name jwtUtil
|
||||
type jwtUtil interface {
|
||||
Validate(string) (*models.JWTAuthUser, error)
|
||||
}
|
||||
|
||||
type ServiceDeps struct {
|
||||
JWT jwtUtil
|
||||
|
||||
/* Публичный ключ для верификации подписи кривой Эдвардса (Edwards curve) */
|
||||
PublicCurveKey string
|
||||
|
||||
/* Приватный ключ для верификации подписи кривой Эдвардса (Edwards curve) */
|
||||
PrivateCurveKey string
|
||||
|
||||
/*
|
||||
Обший секретный знаменатель для шифрования и верификации подписи
|
||||
(должен быть одинаковым для всех микросервисов)
|
||||
*/
|
||||
SignSecret string
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
jwt jwtUtil
|
||||
publicCurveKey string
|
||||
privateCurveKey string
|
||||
signSecret string
|
||||
}
|
||||
|
||||
func New(deps *ServiceDeps) *Service {
|
||||
return &Service{
|
||||
jwt: deps.JWT,
|
||||
publicCurveKey: deps.PublicCurveKey,
|
||||
privateCurveKey: deps.PrivateCurveKey,
|
||||
signSecret: deps.SignSecret,
|
||||
}
|
||||
}
|
||||
|
||||
func (receiver *Service) VerifySignature(signature []byte) (isValid bool, err error) {
|
||||
defer func() {
|
||||
if recovered := recover(); recovered != nil {
|
||||
err = fmt.Errorf("recovered sign error on <VerifySignature> of <EncryptService>: %v", recovered)
|
||||
}
|
||||
}()
|
||||
|
||||
block, _ := pem.Decode([]byte(receiver.publicCurveKey))
|
||||
if block == nil {
|
||||
return false, fmt.Errorf("public key block is nil")
|
||||
}
|
||||
|
||||
rawPublicKey, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed parse public key on <VerifySignature> of <EncryptService>: %w", err)
|
||||
}
|
||||
|
||||
publicKey, ok := rawPublicKey.(ed25519.PublicKey)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("failed convert to ed25519.PrivateKey on <VerifySignature> of <EncryptService>: %w", err)
|
||||
}
|
||||
|
||||
return ed25519.Verify(publicKey, []byte(receiver.signSecret), signature), nil
|
||||
}
|
||||
|
||||
func (receiver *Service) SignCommonSecret() (signature []byte, err error) {
|
||||
defer func() {
|
||||
if recovered := recover(); recovered != nil {
|
||||
err = fmt.Errorf("recovered sign error on <SignCommonSecret> of <EncryptService>: %v", recovered)
|
||||
}
|
||||
}()
|
||||
|
||||
block, _ := pem.Decode([]byte(receiver.privateCurveKey))
|
||||
|
||||
rawPrivateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
return []byte{}, fmt.Errorf("failed parse private key on <SignCommonSecret> of <EncryptService>: %w", err)
|
||||
}
|
||||
|
||||
privateKey, ok := rawPrivateKey.(ed25519.PrivateKey)
|
||||
if !ok {
|
||||
return []byte{}, fmt.Errorf("failed convert to ed25519.PrivateKey on <SignCommonSecret> of <EncryptService>: %w", err)
|
||||
}
|
||||
|
||||
return ed25519.Sign(privateKey, []byte(receiver.signSecret)), nil
|
||||
}
|
||||
|
||||
func (receiver *Service) VerifyJWT(token string) (string, error) {
|
||||
validatedJwtPayload, err := receiver.jwt.Validate(token)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to verify jwt on <VerifyJWT> of <EncryptService>: %w", err)
|
||||
}
|
||||
|
||||
return validatedJwtPayload.ID, nil
|
||||
}
|
@ -1,182 +0,0 @@
|
||||
package encrypt_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/service/encrypt"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/service/encrypt/mocks"
|
||||
)
|
||||
|
||||
var (
|
||||
privateKeyCurve25519 = strings.Replace(
|
||||
`-----BEGIN PRIVATE KEY-----
|
||||
MC4CAQAwBQYDK2VwBCIEIKn0BKwF3vZvODgWAnUIwQhd8de5oZhY48gc23EWfrfs
|
||||
-----END PRIVATE KEY-----`,
|
||||
"\t",
|
||||
"",
|
||||
-1,
|
||||
)
|
||||
|
||||
privateKeyCurve25519Invalid = strings.Replace(
|
||||
`-----BEGIN PRIVATE KEY-----
|
||||
MC4CAQAwBQYDK2VwBCIE3vZvODgWAnUIhd8de5oZhY48gc23EWfrfs
|
||||
-----END PRIVATE KEY-----`,
|
||||
"\t",
|
||||
"",
|
||||
-1,
|
||||
)
|
||||
|
||||
publicKeyCurve25519 = strings.Replace(
|
||||
`-----BEGIN PUBLIC KEY-----
|
||||
MCowBQYDK2VwAyEAEbnIvjIMle4rqVol6K2XUqOxHy1KJoNoZdKJrRUPKL4=
|
||||
-----END PUBLIC KEY-----`,
|
||||
"\t",
|
||||
"",
|
||||
-1,
|
||||
)
|
||||
|
||||
publicKeyCurve25519InvalidLength = strings.Replace(
|
||||
`-----BEGIN PUBLIC KEY-----
|
||||
MowBQYDK2VwA9yEAEbnIvjIMle4rqVol6K2XUqOxHy1KJoNoZdKJrRUPKL4=
|
||||
-----END PUBLIC KEY-----`,
|
||||
"\t",
|
||||
"",
|
||||
-1,
|
||||
)
|
||||
)
|
||||
|
||||
func TestSignCommonSecret(t *testing.T) {
|
||||
t.Run("Успешная подпись общего секрета", func(t *testing.T) {
|
||||
encryptService := encrypt.New(&encrypt.ServiceDeps{
|
||||
PrivateCurveKey: privateKeyCurve25519,
|
||||
SignSecret: "secret",
|
||||
})
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
encryptedText, err := encryptService.SignCommonSecret()
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, encryptedText)
|
||||
assert.NotZero(t, encryptedText)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Ошибка подписи из-за кривого ключа (заголовок имеется)", func(t *testing.T) {
|
||||
encryptService := encrypt.New(&encrypt.ServiceDeps{
|
||||
PrivateCurveKey: privateKeyCurve25519Invalid,
|
||||
SignSecret: "secret",
|
||||
})
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
encryptedText, err := encryptService.SignCommonSecret()
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Empty(t, encryptedText)
|
||||
assert.Zero(t, encryptedText)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Ошибка подписи из-за рандомного кривого ключа", func(t *testing.T) {
|
||||
encryptService := encrypt.New(&encrypt.ServiceDeps{
|
||||
PrivateCurveKey: "testtesttesttest",
|
||||
SignSecret: "secret",
|
||||
})
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
encryptedText, err := encryptService.SignCommonSecret()
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Empty(t, encryptedText)
|
||||
assert.Zero(t, encryptedText)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestVerifySignature(t *testing.T) {
|
||||
t.Run("Успешное подтвеждение подписи", func(t *testing.T) {
|
||||
encryptService := encrypt.New(&encrypt.ServiceDeps{
|
||||
PublicCurveKey: publicKeyCurve25519,
|
||||
PrivateCurveKey: privateKeyCurve25519,
|
||||
SignSecret: "secret",
|
||||
})
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
signature, _ := encryptService.SignCommonSecret()
|
||||
isValid, err := encryptService.VerifySignature(signature)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, isValid)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Неудачное подтверждение подписи из-за невалидности ключа", func(t *testing.T) {
|
||||
encryptService := encrypt.New(&encrypt.ServiceDeps{
|
||||
PublicCurveKey: "teettaegarehah",
|
||||
PrivateCurveKey: privateKeyCurve25519,
|
||||
SignSecret: "secret",
|
||||
})
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
signature, _ := encryptService.SignCommonSecret()
|
||||
isValid, err := encryptService.VerifySignature(signature)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, false, isValid)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Неудачное подтверждение подписи при использовании ключа у которого невалидный размер (слишком большой)", func(t *testing.T) {
|
||||
encryptService := encrypt.New(&encrypt.ServiceDeps{
|
||||
PublicCurveKey: publicKeyCurve25519InvalidLength,
|
||||
PrivateCurveKey: privateKeyCurve25519,
|
||||
SignSecret: "secret",
|
||||
})
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
signature, _ := encryptService.SignCommonSecret()
|
||||
isValid, err := encryptService.VerifySignature(signature)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, false, isValid)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestVerifyJWT(t *testing.T) {
|
||||
jwtToken := "token-token"
|
||||
jwtUser := models.JWTAuthUser{
|
||||
ID: "id1",
|
||||
}
|
||||
|
||||
t.Run("Успешное подтверждение токена", func(t *testing.T) {
|
||||
jwtUtil := mocks.NewJwtUtil(t)
|
||||
encryptService := encrypt.New(&encrypt.ServiceDeps{
|
||||
JWT: jwtUtil,
|
||||
})
|
||||
|
||||
jwtUtil.EXPECT().Validate(jwtToken).Return(&jwtUser, nil).Once()
|
||||
|
||||
id, err := encryptService.VerifyJWT(jwtToken)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, jwtUser.ID, id)
|
||||
})
|
||||
|
||||
t.Run("Ошибка подтверждения токена", func(t *testing.T) {
|
||||
jwtUtil := mocks.NewJwtUtil(t)
|
||||
encryptService := encrypt.New(&encrypt.ServiceDeps{
|
||||
JWT: jwtUtil,
|
||||
})
|
||||
|
||||
jwtUtil.EXPECT().Validate(jwtToken).Return(nil, errors.New("validate jwt error")).Once()
|
||||
|
||||
id, err := encryptService.VerifyJWT(jwtToken)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Empty(t, id)
|
||||
})
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
// Code generated by mockery v2.26.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
models "penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
)
|
||||
|
||||
// JwtUtil is an autogenerated mock type for the jwtUtil type
|
||||
type JwtUtil struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type JwtUtil_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *JwtUtil) EXPECT() *JwtUtil_Expecter {
|
||||
return &JwtUtil_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// Validate provides a mock function with given fields: _a0
|
||||
func (_m *JwtUtil) Validate(_a0 string) (*models.JWTAuthUser, error) {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
var r0 *models.JWTAuthUser
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string) (*models.JWTAuthUser, error)); ok {
|
||||
return rf(_a0)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string) *models.JWTAuthUser); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.JWTAuthUser)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(_a0)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// JwtUtil_Validate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Validate'
|
||||
type JwtUtil_Validate_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Validate is a helper method to define mock.On call
|
||||
// - _a0 string
|
||||
func (_e *JwtUtil_Expecter) Validate(_a0 interface{}) *JwtUtil_Validate_Call {
|
||||
return &JwtUtil_Validate_Call{Call: _e.mock.On("Validate", _a0)}
|
||||
}
|
||||
|
||||
func (_c *JwtUtil_Validate_Call) Run(run func(_a0 string)) *JwtUtil_Validate_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *JwtUtil_Validate_Call) Return(_a0 *models.JWTAuthUser, _a1 error) *JwtUtil_Validate_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *JwtUtil_Validate_Call) RunAndReturn(run func(string) (*models.JWTAuthUser, error)) *JwtUtil_Validate_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewJwtUtil interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewJwtUtil creates a new instance of JwtUtil. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewJwtUtil(t mockConstructorTestingTNewJwtUtil) *JwtUtil {
|
||||
mock := &JwtUtil{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
@ -1,166 +0,0 @@
|
||||
// Code generated by mockery v2.26.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
oauth2 "golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// OauthClient is an autogenerated mock type for the oauthClient type
|
||||
type OauthClient struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type OauthClient_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *OauthClient) EXPECT() *OauthClient_Expecter {
|
||||
return &OauthClient_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// AuthCodeURL provides a mock function with given fields: state, opts
|
||||
func (_m *OauthClient) AuthCodeURL(state string, opts ...oauth2.AuthCodeOption) string {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, state)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func(string, ...oauth2.AuthCodeOption) string); ok {
|
||||
r0 = rf(state, opts...)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// OauthClient_AuthCodeURL_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AuthCodeURL'
|
||||
type OauthClient_AuthCodeURL_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// AuthCodeURL is a helper method to define mock.On call
|
||||
// - state string
|
||||
// - opts ...oauth2.AuthCodeOption
|
||||
func (_e *OauthClient_Expecter) AuthCodeURL(state interface{}, opts ...interface{}) *OauthClient_AuthCodeURL_Call {
|
||||
return &OauthClient_AuthCodeURL_Call{Call: _e.mock.On("AuthCodeURL",
|
||||
append([]interface{}{state}, opts...)...)}
|
||||
}
|
||||
|
||||
func (_c *OauthClient_AuthCodeURL_Call) Run(run func(state string, opts ...oauth2.AuthCodeOption)) *OauthClient_AuthCodeURL_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]oauth2.AuthCodeOption, len(args)-1)
|
||||
for i, a := range args[1:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(oauth2.AuthCodeOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(string), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *OauthClient_AuthCodeURL_Call) Return(_a0 string) *OauthClient_AuthCodeURL_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *OauthClient_AuthCodeURL_Call) RunAndReturn(run func(string, ...oauth2.AuthCodeOption) string) *OauthClient_AuthCodeURL_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Exchange provides a mock function with given fields: ctx, code, opts
|
||||
func (_m *OauthClient) Exchange(ctx context.Context, code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, code)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 *oauth2.Token
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, ...oauth2.AuthCodeOption) (*oauth2.Token, error)); ok {
|
||||
return rf(ctx, code, opts...)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, ...oauth2.AuthCodeOption) *oauth2.Token); ok {
|
||||
r0 = rf(ctx, code, opts...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*oauth2.Token)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, ...oauth2.AuthCodeOption) error); ok {
|
||||
r1 = rf(ctx, code, opts...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// OauthClient_Exchange_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Exchange'
|
||||
type OauthClient_Exchange_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Exchange is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - code string
|
||||
// - opts ...oauth2.AuthCodeOption
|
||||
func (_e *OauthClient_Expecter) Exchange(ctx interface{}, code interface{}, opts ...interface{}) *OauthClient_Exchange_Call {
|
||||
return &OauthClient_Exchange_Call{Call: _e.mock.On("Exchange",
|
||||
append([]interface{}{ctx, code}, opts...)...)}
|
||||
}
|
||||
|
||||
func (_c *OauthClient_Exchange_Call) Run(run func(ctx context.Context, code string, opts ...oauth2.AuthCodeOption)) *OauthClient_Exchange_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]oauth2.AuthCodeOption, len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(oauth2.AuthCodeOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(context.Context), args[1].(string), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *OauthClient_Exchange_Call) Return(_a0 *oauth2.Token, _a1 error) *OauthClient_Exchange_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *OauthClient_Exchange_Call) RunAndReturn(run func(context.Context, string, ...oauth2.AuthCodeOption) (*oauth2.Token, error)) *OauthClient_Exchange_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewOauthClient interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewOauthClient creates a new instance of OauthClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewOauthClient(t mockConstructorTestingTNewOauthClient) *OauthClient {
|
||||
mock := &OauthClient{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
// Code generated by mockery v2.26.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// ServiceClient is an autogenerated mock type for the serviceClient type
|
||||
type ServiceClient[T interface{}] struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type ServiceClient_Expecter[T interface{}] struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *ServiceClient[T]) EXPECT() *ServiceClient_Expecter[T] {
|
||||
return &ServiceClient_Expecter[T]{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// GetUserInformation provides a mock function with given fields: ctx, accessToken
|
||||
func (_m *ServiceClient[T]) GetUserInformation(ctx context.Context, accessToken string) (*T, error) {
|
||||
ret := _m.Called(ctx, accessToken)
|
||||
|
||||
var r0 *T
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*T, error)); ok {
|
||||
return rf(ctx, accessToken)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *T); ok {
|
||||
r0 = rf(ctx, accessToken)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*T)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, accessToken)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ServiceClient_GetUserInformation_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetUserInformation'
|
||||
type ServiceClient_GetUserInformation_Call[T interface{}] struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetUserInformation is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - accessToken string
|
||||
func (_e *ServiceClient_Expecter[T]) GetUserInformation(ctx interface{}, accessToken interface{}) *ServiceClient_GetUserInformation_Call[T] {
|
||||
return &ServiceClient_GetUserInformation_Call[T]{Call: _e.mock.On("GetUserInformation", ctx, accessToken)}
|
||||
}
|
||||
|
||||
func (_c *ServiceClient_GetUserInformation_Call[T]) Run(run func(ctx context.Context, accessToken string)) *ServiceClient_GetUserInformation_Call[T] {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *ServiceClient_GetUserInformation_Call[T]) Return(_a0 *T, _a1 error) *ServiceClient_GetUserInformation_Call[T] {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *ServiceClient_GetUserInformation_Call[T]) RunAndReturn(run func(context.Context, string) (*T, error)) *ServiceClient_GetUserInformation_Call[T] {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewServiceClient interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewServiceClient creates a new instance of ServiceClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewServiceClient[T interface{}](t mockConstructorTestingTNewServiceClient) *ServiceClient[T] {
|
||||
mock := &ServiceClient[T]{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
package oauth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/oauth2"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/utils"
|
||||
)
|
||||
|
||||
/*
|
||||
TODO:
|
||||
|
||||
- Реализовать рандомную генерацию state. Каждый раз при генерации ссылки (auth/link),
|
||||
для этой ссылки должен генерироваться новый state. Так же при реализации этого функционала,
|
||||
необходимо решить, где хранить этот временный state: MongoDB, Reddis, RAM
|
||||
- Покрыть тестами генерацию рандомного state
|
||||
*/
|
||||
|
||||
//go:generate mockery --name serviceClient
|
||||
type serviceClient[T any] interface {
|
||||
GetUserInformation(ctx context.Context, accessToken string) (*T, error)
|
||||
}
|
||||
|
||||
//go:generate mockery --name oauthClient
|
||||
type oauthClient interface {
|
||||
Exchange(ctx context.Context, code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error)
|
||||
AuthCodeURL(state string, opts ...oauth2.AuthCodeOption) string
|
||||
}
|
||||
|
||||
type Deps[T any] struct {
|
||||
Logger *logrus.Logger
|
||||
ServiceClient serviceClient[T]
|
||||
OAuthClient oauthClient
|
||||
}
|
||||
|
||||
type Service[T any] struct {
|
||||
logger *logrus.Logger
|
||||
serviceClient serviceClient[T]
|
||||
oauthClient oauthClient
|
||||
state string
|
||||
}
|
||||
|
||||
func New[T any](deps *Deps[T]) *Service[T] {
|
||||
return &Service[T]{
|
||||
logger: deps.Logger,
|
||||
serviceClient: deps.ServiceClient,
|
||||
oauthClient: deps.OAuthClient,
|
||||
state: utils.GetRandomString(10),
|
||||
}
|
||||
}
|
||||
|
||||
func (receiver *Service[T]) GetUserInformationByCode(ctx context.Context, code string) (*T, error) {
|
||||
token, err := receiver.oauthClient.Exchange(ctx, code)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to exchange token on <GetSocialUserInformationByCode> of <AuthService>: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userInformation, err := receiver.serviceClient.GetUserInformation(ctx, token.AccessToken)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to get user information on <GetSocialUserInformationByCode> of <AuthService>: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return userInformation, nil
|
||||
}
|
||||
|
||||
func (receiver *Service[any]) GenerateAuthURL() string {
|
||||
return receiver.oauthClient.AuthCodeURL(receiver.GetState(), oauth2.AccessTypeOffline)
|
||||
}
|
||||
|
||||
func (receiver *Service[any]) GenerateLinkURL(accessToken string) string {
|
||||
setAccessTokenParam := oauth2.SetAuthURLParam("accessToken", accessToken)
|
||||
|
||||
return receiver.oauthClient.AuthCodeURL(receiver.GetState(), oauth2.AccessTypeOffline, setAccessTokenParam)
|
||||
}
|
||||
|
||||
func (receiver *Service[any]) ValidateState(state string) bool {
|
||||
return state == receiver.state
|
||||
}
|
||||
|
||||
func (receiver *Service[any]) GetState() string {
|
||||
return receiver.state
|
||||
}
|
@ -1,167 +0,0 @@
|
||||
package oauth_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"golang.org/x/oauth2"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/errors"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/service/oauth"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/service/oauth/mocks"
|
||||
)
|
||||
|
||||
type SocialUserInformation struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
var (
|
||||
code = "code"
|
||||
|
||||
socialUserInformation = SocialUserInformation{
|
||||
ID: "userid1",
|
||||
}
|
||||
|
||||
oauthTokens = oauth2.Token{
|
||||
AccessToken: "access-token-auth",
|
||||
RefreshToken: "refresh-token-auth",
|
||||
}
|
||||
)
|
||||
|
||||
func TestGetUserInformationByCode(t *testing.T) {
|
||||
t.Run("Успешное получение информации о пользователе oauth через код", func(t *testing.T) {
|
||||
serviceClient := mocks.NewServiceClient[SocialUserInformation](t)
|
||||
oauthClient := mocks.NewOauthClient(t)
|
||||
oauthService := oauth.New(&oauth.Deps[SocialUserInformation]{
|
||||
Logger: logrus.New(),
|
||||
ServiceClient: serviceClient,
|
||||
OAuthClient: oauthClient,
|
||||
})
|
||||
|
||||
oauthCodeExchangeCall := oauthClient.EXPECT().
|
||||
Exchange(mock.Anything, code).
|
||||
Return(&oauthTokens, nil).
|
||||
Once()
|
||||
|
||||
serviceClient.EXPECT().
|
||||
GetUserInformation(mock.Anything, oauthTokens.AccessToken).
|
||||
Return(&socialUserInformation, nil).
|
||||
NotBefore(oauthCodeExchangeCall).
|
||||
Once()
|
||||
|
||||
information, err := oauthService.GetUserInformationByCode(context.Background(), code)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, &socialUserInformation, information)
|
||||
})
|
||||
|
||||
t.Run("Ошибка при запросе за информацией о пользователе oauth системы", func(t *testing.T) {
|
||||
serviceClient := mocks.NewServiceClient[SocialUserInformation](t)
|
||||
oauthClient := mocks.NewOauthClient(t)
|
||||
oauthService := oauth.New(&oauth.Deps[SocialUserInformation]{
|
||||
Logger: logrus.New(),
|
||||
ServiceClient: serviceClient,
|
||||
OAuthClient: oauthClient,
|
||||
})
|
||||
|
||||
oauthCodeExchangeCall := oauthClient.EXPECT().
|
||||
Exchange(mock.Anything, code).
|
||||
Return(&oauthTokens, nil).
|
||||
Once()
|
||||
|
||||
serviceClient.EXPECT().
|
||||
GetUserInformation(mock.Anything, oauthTokens.AccessToken).
|
||||
Return(nil, errors.ErrEmptyArgs).
|
||||
NotBefore(oauthCodeExchangeCall).
|
||||
Once()
|
||||
|
||||
information, err := oauthService.GetUserInformationByCode(context.Background(), code)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrEmptyArgs.Error())
|
||||
assert.Nil(t, information)
|
||||
})
|
||||
|
||||
t.Run("Ошибка при обмене ключа на токены при получении информации об oauth пользователе", func(t *testing.T) {
|
||||
serviceClient := mocks.NewServiceClient[SocialUserInformation](t)
|
||||
oauthClient := mocks.NewOauthClient(t)
|
||||
oauthService := oauth.New(&oauth.Deps[SocialUserInformation]{
|
||||
Logger: logrus.New(),
|
||||
ServiceClient: serviceClient,
|
||||
OAuthClient: oauthClient,
|
||||
})
|
||||
|
||||
oauthClient.EXPECT().
|
||||
Exchange(mock.Anything, code).
|
||||
Return(nil, errors.ErrEmptyArgs).
|
||||
Once()
|
||||
|
||||
serviceClient.AssertNotCalled(t, "GetUserInformation")
|
||||
|
||||
information, err := oauthService.GetUserInformationByCode(context.Background(), code)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, errors.ErrEmptyArgs.Error())
|
||||
assert.Nil(t, information)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGenerateURL(t *testing.T) {
|
||||
generatedLink := "https://link"
|
||||
accessToken := "access-token"
|
||||
|
||||
t.Run("Успешная генерация ссылки авторизации", func(t *testing.T) {
|
||||
oauthClient := mocks.NewOauthClient(t)
|
||||
oauthService := oauth.New(&oauth.Deps[any]{
|
||||
OAuthClient: oauthClient,
|
||||
})
|
||||
|
||||
oauthClient.EXPECT().AuthCodeURL(oauthService.GetState(), oauth2.AccessTypeOffline).Return(generatedLink).Once()
|
||||
|
||||
assert.Equal(t, generatedLink, oauthService.GenerateAuthURL())
|
||||
})
|
||||
|
||||
t.Run("Успешная генерация ссылки привязки аккаунта", func(t *testing.T) {
|
||||
oauthClient := mocks.NewOauthClient(t)
|
||||
oauthService := oauth.New(&oauth.Deps[any]{
|
||||
OAuthClient: oauthClient,
|
||||
})
|
||||
|
||||
oauthClient.EXPECT().
|
||||
AuthCodeURL(
|
||||
oauthService.GetState(),
|
||||
oauth2.AccessTypeOffline,
|
||||
oauth2.SetAuthURLParam("accessToken", accessToken),
|
||||
).
|
||||
Return(generatedLink).
|
||||
Once()
|
||||
|
||||
assert.Equal(t, generatedLink, oauthService.GenerateLinkURL(accessToken))
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetState(t *testing.T) {
|
||||
t.Run("Успешное получение state", func(t *testing.T) {
|
||||
oauthService := oauth.New(&oauth.Deps[any]{})
|
||||
|
||||
assert.NotEmpty(t, oauthService.GetState())
|
||||
assert.NotNil(t, oauthService.GetState())
|
||||
assert.NotZero(t, oauthService.GetState())
|
||||
})
|
||||
}
|
||||
|
||||
func TestValidateState(t *testing.T) {
|
||||
t.Run("Невалидный state", func(t *testing.T) {
|
||||
oauthService := oauth.New(&oauth.Deps[any]{})
|
||||
|
||||
assert.Equal(t, false, oauthService.ValidateState(""))
|
||||
})
|
||||
|
||||
t.Run("Валидный state", func(t *testing.T) {
|
||||
oauthService := oauth.New(&oauth.Deps[any]{})
|
||||
|
||||
assert.Equal(t, true, oauthService.ValidateState(oauthService.GetState()))
|
||||
})
|
||||
}
|
3
internal/swagger/generate.go
Normal file
3
internal/swagger/generate.go
Normal file
@ -0,0 +1,3 @@
|
||||
package swagger
|
||||
|
||||
//go:generate oapi-codegen --config oapi-codegen.yaml ../../openapi.yaml
|
7
internal/swagger/oapi-codegen.yaml
Normal file
7
internal/swagger/oapi-codegen.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
output: server.gen.go
|
||||
package: swagger
|
||||
generate:
|
||||
# other servers are available!
|
||||
echo-server: true
|
||||
models: true
|
||||
embedded-spec: true
|
572
internal/swagger/server.gen.go
Normal file
572
internal/swagger/server.gen.go
Normal file
@ -0,0 +1,572 @@
|
||||
// Package api provides primitives to interact with the openapi HTTP API.
|
||||
//
|
||||
// Code generated by github.com/deepmap/oapi-codegen version v1.12.4 DO NOT EDIT.
|
||||
package swagger
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/deepmap/oapi-codegen/pkg/runtime"
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// Defines values for RecordType.
|
||||
const (
|
||||
BuyCart RecordType = "buyCart"
|
||||
DeclinedPayment RecordType = "declinedPayment"
|
||||
SubsriptionEnd RecordType = "subsriptionEnd"
|
||||
SuccessfulPayment RecordType = "successfulPayment"
|
||||
TimeoutPayment RecordType = "timeoutPayment"
|
||||
)
|
||||
|
||||
// Account defines model for Account.
|
||||
type Account struct {
|
||||
Id *string `json:"_id,omitempty"`
|
||||
Cart *Cart `json:"cart,omitempty"`
|
||||
IsDeleted *bool `json:"isDeleted,omitempty"`
|
||||
UserId *string `json:"userId,omitempty"`
|
||||
Wallet *Wallet `json:"wallet,omitempty"`
|
||||
}
|
||||
|
||||
// Cart defines model for Cart.
|
||||
type Cart = []string
|
||||
|
||||
// Record defines model for Record.
|
||||
type Record struct {
|
||||
Comment *string `json:"comment,omitempty"`
|
||||
CreatedAt *time.Time `json:"createdAt,omitempty"`
|
||||
Id *string `json:"id,omitempty"`
|
||||
|
||||
// Subject я пока не могу предположить, какие будут фильтры по истории, поэтому предлагаю в это поле просто класть строку с json. ибо для каждого типа записи она своя.
|
||||
Subject *string `json:"subject,omitempty"`
|
||||
Type *RecordType `json:"type,omitempty"`
|
||||
UserId *string `json:"userId,omitempty"`
|
||||
}
|
||||
|
||||
// RecordType defines model for Record.Type.
|
||||
type RecordType string
|
||||
|
||||
// Wallet defines model for Wallet.
|
||||
type Wallet struct {
|
||||
Cash *int64 `json:"cash,omitempty"`
|
||||
Currency *string `json:"currency,omitempty"`
|
||||
|
||||
// Money деньги на счету в копейках. Чтобы при перессчётах не возникало денег изниоткуда. фиксируемся к одной валюте, она будет внутренней, никому её не покажем
|
||||
Money *int64 `json:"money,omitempty"`
|
||||
}
|
||||
|
||||
// PaginationAccountsParams defines parameters for PaginationAccounts.
|
||||
type PaginationAccountsParams struct {
|
||||
// P Номер страницы, начиная с 0
|
||||
P *int `form:"p,omitempty" json:"p,omitempty"`
|
||||
|
||||
// S размер страницы
|
||||
S *int `form:"s,omitempty" json:"s,omitempty"`
|
||||
}
|
||||
|
||||
// RemoveFromCartParams defines parameters for RemoveFromCart.
|
||||
type RemoveFromCartParams struct {
|
||||
Id string `form:"id" json:"id"`
|
||||
}
|
||||
|
||||
// Add2cartJSONBody defines parameters for Add2cart.
|
||||
type Add2cartJSONBody struct {
|
||||
Id *string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
// PayCartJSONBody defines parameters for PayCart.
|
||||
type PayCartJSONBody struct {
|
||||
// Id айдишник для того, чтобы указать сервису оплаты, какой юзер оплатил
|
||||
Id *string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
// UpdateCurrenciesJSONBody defines parameters for UpdateCurrencies.
|
||||
type UpdateCurrenciesJSONBody = []string
|
||||
|
||||
// GetHistoryParams defines parameters for GetHistory.
|
||||
type GetHistoryParams struct {
|
||||
// P Номер страницы, начиная с 0
|
||||
P *int `form:"p,omitempty" json:"p,omitempty"`
|
||||
|
||||
// S размер страницы
|
||||
S *int `form:"s,omitempty" json:"s,omitempty"`
|
||||
}
|
||||
|
||||
// ChangeCurrencyJSONBody defines parameters for ChangeCurrency.
|
||||
type ChangeCurrencyJSONBody struct {
|
||||
Currency *string `json:"currency,omitempty"`
|
||||
}
|
||||
|
||||
// RequestMoneyJSONBody defines parameters for RequestMoney.
|
||||
type RequestMoneyJSONBody struct {
|
||||
Cash *int `json:"cash,omitempty"`
|
||||
}
|
||||
|
||||
// PutMoneyJSONBody defines parameters for PutMoney.
|
||||
type PutMoneyJSONBody struct {
|
||||
Cash *int `json:"cash,omitempty"`
|
||||
Currency *string `json:"currency,omitempty"`
|
||||
Id *string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
// Add2cartJSONRequestBody defines body for Add2cart for application/json ContentType.
|
||||
type Add2cartJSONRequestBody Add2cartJSONBody
|
||||
|
||||
// PayCartJSONRequestBody defines body for PayCart for application/json ContentType.
|
||||
type PayCartJSONRequestBody PayCartJSONBody
|
||||
|
||||
// UpdateCurrenciesJSONRequestBody defines body for UpdateCurrencies for application/json ContentType.
|
||||
type UpdateCurrenciesJSONRequestBody = UpdateCurrenciesJSONBody
|
||||
|
||||
// Add2historyJSONRequestBody defines body for Add2history for application/json ContentType.
|
||||
type Add2historyJSONRequestBody = Record
|
||||
|
||||
// ChangeCurrencyJSONRequestBody defines body for ChangeCurrency for application/json ContentType.
|
||||
type ChangeCurrencyJSONRequestBody ChangeCurrencyJSONBody
|
||||
|
||||
// RequestMoneyJSONRequestBody defines body for RequestMoney for application/json ContentType.
|
||||
type RequestMoneyJSONRequestBody RequestMoneyJSONBody
|
||||
|
||||
// PutMoneyJSONRequestBody defines body for PutMoney for application/json ContentType.
|
||||
type PutMoneyJSONRequestBody PutMoneyJSONBody
|
||||
|
||||
// ServerInterface represents all server handlers.
|
||||
type ServerInterface interface {
|
||||
// удалить собственный аккаунт
|
||||
// (DELETE /account)
|
||||
DeleteAccount(ctx echo.Context) error
|
||||
// Получение текущего аккаунта юзера
|
||||
// (GET /account)
|
||||
GetAccount(ctx echo.Context) error
|
||||
// создать новый аккаунт
|
||||
// (POST /account)
|
||||
AddAccount(ctx echo.Context) error
|
||||
// удалить аккаунт по айди
|
||||
// (DELETE /account/{accountId})
|
||||
DeleteDirectAccount(ctx echo.Context, accountId string) error
|
||||
// получить аккаунт по айди
|
||||
// (GET /account/{accountId})
|
||||
GetDirectAccount(ctx echo.Context, accountId string) error
|
||||
// списко аккаунтов с пагинацией
|
||||
// (GET /accounts)
|
||||
PaginationAccounts(ctx echo.Context, params PaginationAccountsParams) error
|
||||
// удаляем из корзины тариф
|
||||
// (DELETE /cart)
|
||||
RemoveFromCart(ctx echo.Context, params RemoveFromCartParams) error
|
||||
// добавляем в корзину тариф
|
||||
// (PUT /cart)
|
||||
Add2cart(ctx echo.Context) error
|
||||
// оплатить козину
|
||||
// (POST /cart/pay)
|
||||
PayCart(ctx echo.Context) error
|
||||
// получить список одобренных валют
|
||||
// (GET /currencies)
|
||||
GetCurrencies(ctx echo.Context) error
|
||||
// обновляет список одобренных валют
|
||||
// (PATCH /currencies)
|
||||
UpdateCurrencies(ctx echo.Context) error
|
||||
// получение лога событий связанных с аккаунтом
|
||||
// (GET /history)
|
||||
GetHistory(ctx echo.Context, params GetHistoryParams) error
|
||||
// публикация лога в истории
|
||||
// (POST /history)
|
||||
Add2history(ctx echo.Context) error
|
||||
// изменить валюту кошелька
|
||||
// (PATCH /wallet)
|
||||
ChangeCurrency(ctx echo.Context) error
|
||||
// запрос на получение ссылки на оплату
|
||||
// (POST /wallet)
|
||||
RequestMoney(ctx echo.Context) error
|
||||
// зачислить деньги на кошелёк
|
||||
// (PUT /wallet)
|
||||
PutMoney(ctx echo.Context) error
|
||||
}
|
||||
|
||||
// ServerInterfaceWrapper converts echo contexts to parameters.
|
||||
type ServerInterfaceWrapper struct {
|
||||
Handler ServerInterface
|
||||
}
|
||||
|
||||
// DeleteAccount converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) DeleteAccount(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.DeleteAccount(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetAccount converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) GetAccount(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.GetAccount(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// AddAccount converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) AddAccount(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.AddAccount(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteDirectAccount converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) DeleteDirectAccount(ctx echo.Context) error {
|
||||
var err error
|
||||
// ------------- Path parameter "accountId" -------------
|
||||
var accountId string
|
||||
|
||||
err = runtime.BindStyledParameterWithLocation("simple", false, "accountId", runtime.ParamLocationPath, ctx.Param("accountId"), &accountId)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter accountId: %s", err))
|
||||
}
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.DeleteDirectAccount(ctx, accountId)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetDirectAccount converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) GetDirectAccount(ctx echo.Context) error {
|
||||
var err error
|
||||
// ------------- Path parameter "accountId" -------------
|
||||
var accountId string
|
||||
|
||||
err = runtime.BindStyledParameterWithLocation("simple", false, "accountId", runtime.ParamLocationPath, ctx.Param("accountId"), &accountId)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter accountId: %s", err))
|
||||
}
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.GetDirectAccount(ctx, accountId)
|
||||
return err
|
||||
}
|
||||
|
||||
// PaginationAccounts converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) PaginationAccounts(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
// Parameter object where we will unmarshal all parameters from the context
|
||||
var params PaginationAccountsParams
|
||||
// ------------- Optional query parameter "p" -------------
|
||||
|
||||
err = runtime.BindQueryParameter("form", false, false, "p", ctx.QueryParams(), ¶ms.P)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter p: %s", err))
|
||||
}
|
||||
|
||||
// ------------- Optional query parameter "s" -------------
|
||||
|
||||
err = runtime.BindQueryParameter("form", false, false, "s", ctx.QueryParams(), ¶ms.S)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter s: %s", err))
|
||||
}
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.PaginationAccounts(ctx, params)
|
||||
return err
|
||||
}
|
||||
|
||||
// RemoveFromCart converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) RemoveFromCart(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
// Parameter object where we will unmarshal all parameters from the context
|
||||
var params RemoveFromCartParams
|
||||
// ------------- Required query parameter "id" -------------
|
||||
|
||||
err = runtime.BindQueryParameter("form", true, true, "id", ctx.QueryParams(), ¶ms.Id)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err))
|
||||
}
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.RemoveFromCart(ctx, params)
|
||||
return err
|
||||
}
|
||||
|
||||
// Add2cart converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) Add2cart(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.Add2cart(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// PayCart converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) PayCart(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.PayCart(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetCurrencies converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) GetCurrencies(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.GetCurrencies(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateCurrencies converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) UpdateCurrencies(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.UpdateCurrencies(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetHistory converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) GetHistory(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
// Parameter object where we will unmarshal all parameters from the context
|
||||
var params GetHistoryParams
|
||||
// ------------- Optional query parameter "p" -------------
|
||||
|
||||
err = runtime.BindQueryParameter("form", false, false, "p", ctx.QueryParams(), ¶ms.P)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter p: %s", err))
|
||||
}
|
||||
|
||||
// ------------- Optional query parameter "s" -------------
|
||||
|
||||
err = runtime.BindQueryParameter("form", false, false, "s", ctx.QueryParams(), ¶ms.S)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter s: %s", err))
|
||||
}
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.GetHistory(ctx, params)
|
||||
return err
|
||||
}
|
||||
|
||||
// Add2history converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) Add2history(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.Add2history(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ChangeCurrency converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) ChangeCurrency(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.ChangeCurrency(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// RequestMoney converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) RequestMoney(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.RequestMoney(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// PutMoney converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) PutMoney(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.PutMoney(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// This is a simple interface which specifies echo.Route addition functions which
|
||||
// are present on both echo.Echo and echo.Group, since we want to allow using
|
||||
// either of them for path registration
|
||||
type EchoRouter interface {
|
||||
CONNECT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
TRACE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
}
|
||||
|
||||
// RegisterHandlers adds each server route to the EchoRouter.
|
||||
func RegisterHandlers(router EchoRouter, si ServerInterface) {
|
||||
RegisterHandlersWithBaseURL(router, si, "")
|
||||
}
|
||||
|
||||
// Registers handlers, and prepends BaseURL to the paths, so that the paths
|
||||
// can be served under a prefix.
|
||||
func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
|
||||
|
||||
wrapper := ServerInterfaceWrapper{
|
||||
Handler: si,
|
||||
}
|
||||
|
||||
router.DELETE(baseURL+"/account", wrapper.DeleteAccount)
|
||||
router.GET(baseURL+"/account", wrapper.GetAccount)
|
||||
router.POST(baseURL+"/account", wrapper.AddAccount)
|
||||
router.DELETE(baseURL+"/account/:accountId", wrapper.DeleteDirectAccount)
|
||||
router.GET(baseURL+"/account/:accountId", wrapper.GetDirectAccount)
|
||||
router.GET(baseURL+"/accounts", wrapper.PaginationAccounts)
|
||||
router.DELETE(baseURL+"/cart", wrapper.RemoveFromCart)
|
||||
router.PUT(baseURL+"/cart", wrapper.Add2cart)
|
||||
router.POST(baseURL+"/cart/pay", wrapper.PayCart)
|
||||
router.GET(baseURL+"/currencies", wrapper.GetCurrencies)
|
||||
router.PATCH(baseURL+"/currencies", wrapper.UpdateCurrencies)
|
||||
router.GET(baseURL+"/history", wrapper.GetHistory)
|
||||
router.POST(baseURL+"/history", wrapper.Add2history)
|
||||
router.PATCH(baseURL+"/wallet", wrapper.ChangeCurrency)
|
||||
router.POST(baseURL+"/wallet", wrapper.RequestMoney)
|
||||
router.PUT(baseURL+"/wallet", wrapper.PutMoney)
|
||||
|
||||
}
|
||||
|
||||
// Base64 encoded, gzipped, json marshaled Swagger object
|
||||
var swaggerSpec = []string{
|
||||
|
||||
"H4sIAAAAAAAC/+xb3W4bx/V/lcH+/xcJSlFk4tax7hy5H7koELgwctEaxZocSpuSu8zuMq0qCBBF105A",
|
||||
"2aofwC3Qm96uKK61IrnUK5x5o+Kcmf0eSrIkf6ToTUztzs6cOed3fudjJrtGy+n1HZvbvmds7Bpea5v3",
|
||||
"TPp5v9VyBraPP/uu0+eub3F68Uerjf/wv5i9fpcbG8YXjbudZufu3SetzhfNVvvuvXt3Pr/XaDaNmuHv",
|
||||
"9HGE57uWvWXs1YyW6dKU/+/yjrFh/N96tv66Wnx9E8fs1QzLe8C73OfF5Tpm1+PpzE8cp8tNG4cPPO5+",
|
||||
"dQPR/mx2u/xS4b6Ro/b20hmcJ9/yFgm8qTZn+bznFQT5/UWSXOfVY80G1APTdc0d/Pshbzluu2rAltPr",
|
||||
"cWnZTFPiiIkX4gCWTAxhCiHMIYA5g3NY4lNYiBETz2nAnc+0lnW56fP2fZq347g90zc2jLbp8zXf6nHd",
|
||||
"JzcBkjeQat/YNdrca7lW37ccW24EhYYZBAxiCBksYAknYsTgXOxDCFN6PYclvIFIHIjDGsPBMIMIRx+L",
|
||||
"EUzFSBww8RQimItDcSD2xZhmZRCJISpB7EMEUU3q50WqoXQJ1N4JBOIlg0miWLVuKEct5US49hwC/EMc",
|
||||
"MvpnH6VHdQ/Zt55j1xlEcIwjpzDH3aGwb2CKu0JzHUAE57jZUwjgHAWEiMESYgjQlhNYiqO6Ucv0vGv4",
|
||||
"pmt1Ot51cfl4byX6dg1uD3o4sTdotbjndQbdr80dwlvNaPNW17J5O3uC0HAGfvbgyWCH3Igs7Cmz/tJu",
|
||||
"I+IzpOgmr0h0M0LQOfg3KUWUPMr0tgvrNBt3G81a5gaW7f/iTraGZft8i7vkNgPX5XZrpyjmw0df6nbU",
|
||||
"c2y+U4U8+WssDuEELS/tLp5DKA4QkhNEzBLOIYQzxI74W53BvwmyxwRrxDKCM0TsiiF+K16JAxypPGgC",
|
||||
"SziFGCLC3lxiMcR3cILolO+QKGboPRDUpfPMEItiX4wghIUYEngRmlOIYQlnOHEAc/FSHEBYSzArPRCl",
|
||||
"x/cxuiI5VUzrndWYEkR5XCheKSmV18MbXC0P+Ktao2pyfGTZHUej83/Acc5xafMTUvlQ/iJ5pZNH6Ieo",
|
||||
"3Ql5Z8DWMqKQIwKYIDPQztRO5uIQTmGJKkL1oJqYeCpGEMNMPEN1o7ZQBLKv2IdTiCBGi0byyQ/01SHq",
|
||||
"pE6u5hO2Ngee7/S4y9YKYiX0IkYkW04iyTlzFA1iEnYBkVEzvueuJ5XRrDfqDQSo0+e22beMDePzeqOO",
|
||||
"XtU3/W3ykXUzSyjaFNc1SsWNLyAUzyGQAEBaRsyOcGUmwQVz8Qq1K8ZkZnREEydAXzdkypAkLzXD5V7f",
|
||||
"sT3pp581GpqAMRJDQv8PhMowXSWzR0EKCHCndxpNjfyvIUTNpRFCGRBiApc36PVMd4fWVEtEivbJGXPI",
|
||||
"EWN0j8K6aEJzi0g7USUS8RbXBEHCWYoi9D8C5lHq7afo3eSJIRMv4ZRwEFCwGqoYhy47qjP4O5zBFCJS",
|
||||
"TwSzwnC5xCizVwSnjKhlRvsIahKKpA+5J8UzuH9kGSnVREavExWYJ/g5Mwf+tuNafyXjVgz9a+5fbOWW",
|
||||
"Y/sqzTH7/a7Vom/XMaRmqe5l6V6yBDHBJbjJaUMh51pAwU/uaD75F8FBBv0VDHFETCgOSmiDf5YFY/TB",
|
||||
"TIzEj8jhOGMJ4zkzrwBe3/F06deQYoWyLiPVTDRoTukmXaaGXD5En2BEMuleQ/FjyvHHYowIqaDhfru9",
|
||||
"Eg3ND4IGpYjg3XFIpmmKQKs0rTXfXi0l5PVd9eOr9t6F5IzEjK49JVsQY0kKiWAh151gHBxKSei/C0kG",
|
||||
"MgotMRWXWcMUgzRFmUUtF3hytFsJOiuY/oHl8laOCfqma/a4z13ccGULQYnLKlbBcG9sUNQyaoZt9qii",
|
||||
"SvRD2PpuYLlYk/rugNdywCnnj48/ouCzilNeE2sX3W0FtVwcwcrOfS4phbT9VoHrHYOszNH4aEpOGosx",
|
||||
"5rvLIuxCXdz5yWHuIwiFHyuOc5JeE8k5KiWd63FdzpRIYRFxeAUSS8Q4lXEjKmhkFJElk+oQUFgRzyBk",
|
||||
"P2OMvAQDeShLPXTK51TKYT651ExfQfXX5pZl05/3k61chuvXKlffL8kkxlSiBahR+veIiSFrUEHW7zrt",
|
||||
"rIdHsP9uwN2dDPd9I4/vNu+Yg65vbDR01VqFTPdJWXqhrri+p1+/qRPgpt5WbssNSk25ZlPXMUi7i+mP",
|
||||
"K3ltuT+oL3bf3q/Letah7TZyHektMy2cEWBwTgWEhNwzIvCzlf6atKGzXKfoDg95z/me/8p1eqoZVXIF",
|
||||
"HXKsi6n6Wj2oK+YQuZRhKWuwYktgtQHit+daysNjRYkhxBntntFPnEc8XZEuiCOsK3Uy5r/NzEaGompj",
|
||||
"4K8Qv5AiEPFTB3VCsV81eFXnWispIpjqIMmXsljWFRiftSQW0Mbc87902js3cHfrFjuT5LqXA4V6xse5",
|
||||
"1s4y6Q6mZhh9eKjkpUzgUpbyQrAkDr7eN8lA+kJ1DdNIpLEJRLIhyXBm6h7G1PIU+zCjUAIRVaVyvGxe",
|
||||
"iMNPKM6oHv4JNVLopOGNnIrOTQiIJ0mBhpT1FIvuT/NdEQqQuZ4nlcDqC+roq7OCcdrJjalBFouxrDLT",
|
||||
"Dh4OUVlu2dBR2vqh7c6p6I9UNl1NeHR50x9stqb6Q2kek1Xs+X7wpNx+DFnW6KRNPycdrcmuadJtVOnX",
|
||||
"5Aq6l5qZyhxDpUoy9i/z6pPKmlFb+0D2C0udWMRWRVfJCU1JV1IBug3H+U5utsEaqySX1F0fw5zOd2S3",
|
||||
"ewnnSuIRo0OfQqc4ffkK3sAM142YojbZGT+kDni9apls3rESJHVdpWgxljZW51Mya07rLwjkhpckPLWx",
|
||||
"U63m6KKaSCbnN7dJk5eVVKqDoHaR8D2db2Q5dNJqzRxmVFbTLKMn1ZfKjUAw5I8V3g1lv9dajbgn22Bw",
|
||||
"5bzhqolbXnuZU2bg0VG3PBFT9lfVVKUG38xG3VCPuUN6eez26HcPjJqxef+B8TiXbV9y3H7d5DnNa4Pc",
|
||||
"adhlNWqxeFxKCksOyWQfI5srp+TkrJESKtNvbVdV+6jfNn1e0u71HPm2FFt2FC0iH5m2Oi7g7SoGj1W7",
|
||||
"iBKKSvV9HQUiUrctz3fcnYtg+hs15H/F9H9DMa1u1Fyrls6uLLAUJbfAr5pG21wmncmp4pgi1xndBRFH",
|
||||
"STOJQI5lc7mYXuTwngA8f9xTLYu2U4xflymuovMr1jh6NZd0JkZ0eE/XGcQzmR0nWsMEtHDJR6sPdP/s",
|
||||
"wljKpeWmX3rYmqTxEG4kadWBpBiqPiJVsga6cpWCdHZTIigTVsDklJVOZtrYRlTQyWwxuWw9cTufUB44",
|
||||
"lalwmlWn2WmsjgfxkZz0XJ064Zvw02RlmZpPVEUU5eTFqUq3EZjsb2KaP6IbUtnYen7wKyTnmAq9pGYQ",
|
||||
"z+hqmkpKVcZOp+WFpK9wWKguW1AhE1PuccZgxrJEPb2kodJtMsRL6qieJcMoKyzf95LcrIoFyZRkmTml",
|
||||
"PPvpgVxypUbey4nIrmF29k2biuWNm0pCvblt2ltJQN65tbxaf+9IRuifUPIqhuq4J58+IQBKkJNM21h5",
|
||||
"rF71sVgWUQVHuwW+jmRMpUAqy7ALHCVHPYpsVh+8rzHxlBZfZFeuCtRDmL+o+sEhujO3hbweJt3kWLyg",
|
||||
"KmkBUZl1ArlkehOKflYK2tySuGJWEcsbYeWauHCBhNgiJpJaFm+SpNSkuTZVcamH0oN+S7fpbs2hqncA",
|
||||
"G43G1S6Z7d1q7tO17D8V3Xrb9/vexvr6luNsdXndHVzNyS/yPnkWe5qBK+2HoJP8XNunLtw2y+Mg62jA",
|
||||
"nJELRHAMMzEqe08BznHxBlLuQCJBVFTF0wqX0naXJa+XWpHFBVVld6py9DQHmzHEA3VrVBKgaVUnsTJp",
|
||||
"NqkXdEkydzNSRwulpsvgA4G59jZxpPZ+et7v/7B7Qi3ZYWb9Qm8wKKU0txWKKp6R5kRp+le6FVySQ+MJ",
|
||||
"pGf5UNN0K14qKl5UMKoVZNITFSM4T7LQXIzOpkgxpJkj148i4CefyP9HRDs8v0M1XG1Q80Eu1RdH2QdJ",
|
||||
"pr/3eO8/AQAA//8nG+8kJDMAAA==",
|
||||
}
|
||||
|
||||
// GetSwagger returns the content of the embedded swagger specification file
|
||||
// or error if failed to decode
|
||||
func decodeSpec() ([]byte, error) {
|
||||
zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, ""))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error base64 decoding spec: %s", err)
|
||||
}
|
||||
zr, err := gzip.NewReader(bytes.NewReader(zipped))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decompressing spec: %s", err)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
_, err = buf.ReadFrom(zr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decompressing spec: %s", err)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
var rawSpec = decodeSpecCached()
|
||||
|
||||
// a naive cached of a decoded swagger spec
|
||||
func decodeSpecCached() func() ([]byte, error) {
|
||||
data, err := decodeSpec()
|
||||
return func() ([]byte, error) {
|
||||
return data, err
|
||||
}
|
||||
}
|
||||
|
||||
// Constructs a synthetic filesystem for resolving external references when loading openapi specifications.
|
||||
func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) {
|
||||
var res = make(map[string]func() ([]byte, error))
|
||||
if len(pathToFile) > 0 {
|
||||
res[pathToFile] = rawSpec
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// GetSwagger returns the Swagger specification corresponding to the generated code
|
||||
// in this file. The external references of Swagger specification are resolved.
|
||||
// The logic of resolving external references is tightly connected to "import-mapping" feature.
|
||||
// Externally referenced files must be embedded in the corresponding golang packages.
|
||||
// Urls can be supported but this task was out of the scope.
|
||||
func GetSwagger() (swagger *openapi3.T, err error) {
|
||||
var resolvePath = PathToRawSpec("")
|
||||
|
||||
loader := openapi3.NewLoader()
|
||||
loader.IsExternalRefsAllowed = true
|
||||
loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) {
|
||||
var pathToFile = url.String()
|
||||
pathToFile = path.Clean(pathToFile)
|
||||
getSpec, ok := resolvePath[pathToFile]
|
||||
if !ok {
|
||||
err1 := fmt.Errorf("path not found: %s", pathToFile)
|
||||
return nil, err1
|
||||
}
|
||||
return getSpec()
|
||||
}
|
||||
var specData []byte
|
||||
specData, err = rawSpec()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
swagger, err = loader.LoadFromData(specData)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
@ -3,7 +3,7 @@ package utils
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/errors"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
|
||||
)
|
||||
|
||||
var clientErrors = map[int]error{
|
||||
|
@ -4,8 +4,8 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/errors"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||
)
|
||||
|
||||
var httpStatuses = map[error]int{
|
||||
|
@ -8,8 +8,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
jsonUtil "penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/json"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||
jsonUtil "penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/json"
|
||||
)
|
||||
|
||||
type JWT[T any] struct {
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/utils"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
|
||||
)
|
||||
|
||||
func TestJWT(t *testing.T) {
|
||||
|
@ -3,8 +3,8 @@ package utils
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/validate"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/validate"
|
||||
)
|
||||
|
||||
func ValidateConfigurationURLs(config *models.ServiceConfiguration) error {
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/array"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/array"
|
||||
)
|
||||
|
||||
func TestContains(t *testing.T) {
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/array"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/array"
|
||||
)
|
||||
|
||||
func TestFilter(t *testing.T) {
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/convert"
|
||||
)
|
||||
|
||||
func buildRequest(ctx context.Context, settings *RequestSettings) *resty.Request {
|
||||
@ -18,11 +17,6 @@ func buildRequest(ctx context.Context, settings *RequestSettings) *resty.Request
|
||||
request.SetBody(settings.Body)
|
||||
}
|
||||
|
||||
if settings.Formdata != nil {
|
||||
formdata, _ := convert.ObjectToStringMap(settings.Formdata, "formdata")
|
||||
request.SetFormData(formdata)
|
||||
}
|
||||
|
||||
if settings.QueryParams != nil {
|
||||
request.SetQueryParams(settings.QueryParams)
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/json"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/json"
|
||||
)
|
||||
|
||||
func parseResponse[T any](body []byte, response *http.Response) (*T, error) {
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/utils"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/utils"
|
||||
)
|
||||
|
||||
func TestGetFilledFieldsCount(t *testing.T) {
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/utils"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/utils"
|
||||
)
|
||||
|
||||
func TestMergeMaps(t *testing.T) {
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/utils"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/utils"
|
||||
)
|
||||
|
||||
func TestGetRandomString(t *testing.T) {
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/validate"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/validate"
|
||||
)
|
||||
|
||||
func TestIsStringEmpty(t *testing.T) {
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/validate"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/validate"
|
||||
)
|
||||
|
||||
func TestValidateURL(t *testing.T) {
|
||||
|
Loading…
Reference in New Issue
Block a user