diff --git a/go.mod b/go.mod index 55b0aee..c4dc3ba 100644 --- a/go.mod +++ b/go.mod @@ -6,24 +6,35 @@ require ( git.ex.umbach.dev/Alex/roese-utils v1.0.21 github.com/gofiber/fiber/v2 v2.49.2 github.com/gofiber/websocket/v2 v2.1.6 - github.com/google/uuid v1.3.1 + github.com/google/uuid v1.6.0 github.com/joho/godotenv v1.5.1 github.com/rs/zerolog v1.31.0 github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee - golang.org/x/crypto v0.15.0 + golang.org/x/crypto v0.23.0 gorm.io/driver/mysql v1.5.2 gorm.io/gorm v1.25.5 ) require ( + cloud.google.com/go/auth v0.4.1 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect + cloud.google.com/go/compute/metadata v0.3.0 // indirect github.com/andybalholm/brotli v1.0.6 // indirect github.com/fasthttp/websocket v1.5.7 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.16.0 // indirect github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/gofiber/utils v1.1.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.4 // indirect github.com/gorilla/schema v1.2.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect @@ -36,7 +47,17 @@ require ( github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.51.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect - golang.org/x/net v0.18.0 // indirect - golang.org/x/sys v0.14.0 // indirect - golang.org/x/text v0.14.0 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/oauth2 v0.20.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/api v0.181.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.1 // indirect ) diff --git a/go.sum b/go.sum index ea5426e..e0dcf8a 100644 --- a/go.sum +++ b/go.sum @@ -1,20 +1,43 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.113.0 h1:g3C70mn3lWfckKBiCVsAshabrDg01pQ0pnX1MNtnMkA= +cloud.google.com/go/auth v0.4.1 h1:Z7YNIhlWRtrnKlZke7z3GMqzvuYzdc2z98F9D1NV5Hg= +cloud.google.com/go/auth v0.4.1/go.mod h1:QVBuVEKpCn4Zp58hzRGvL0tjRGU0YqdRTdCHM1IHnro= +cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= +cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= +cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= +cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= git.ex.umbach.dev/Alex/roese-utils v1.0.19 h1:o7WiO+vajQm2M7/y5IYFM9uuBFBc8Y4LIymmx+LBgo8= git.ex.umbach.dev/Alex/roese-utils v1.0.19/go.mod h1:hFcnKQl6nuGFEMCxK/eVQBUD6ixBFlAaiy4E2aQqUL8= git.ex.umbach.dev/Alex/roese-utils v1.0.20 h1:uGAuGE66qhtOhTWOAEDoo5+3Xt9Yw8hruu/HuCNnjmY= git.ex.umbach.dev/Alex/roese-utils v1.0.20/go.mod h1:hFcnKQl6nuGFEMCxK/eVQBUD6ixBFlAaiy4E2aQqUL8= git.ex.umbach.dev/Alex/roese-utils v1.0.21 h1:ae1AHQh8UHJVLbpk5Gf4S5IP0EEWGD1JFIeX9cIcYcc= git.ex.umbach.dev/Alex/roese-utils v1.0.21/go.mod h1:hFcnKQl6nuGFEMCxK/eVQBUD6ixBFlAaiy4E2aQqUL8= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fasthttp/websocket v1.5.7 h1:0a6o2OfeATvtGgoMKleURhLT6JqWPg7fYfWnH4KHau4= github.com/fasthttp/websocket v1.5.7/go.mod h1:bC4fxSono9czeXHQUVKxsC0sNjbm7lPJR04GDFqClfU= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -36,8 +59,39 @@ github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM= github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0= github.com/gofiber/websocket/v2 v2.1.6 h1:k4z+YqzGUwbCQJCIW+mDJF2iCcBfRY7BJGUa2k+VHXo= github.com/gofiber/websocket/v2 v2.1.6/go.mod h1:o+oXFwHjavIiM2KWo/MNpcIOruS0am16h3efqnjXLis= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg= +github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/schema v1.2.1 h1:tjDxcmdb+siIqkTNoV+qRH2mjYdr2hHe5MKXbp61ziM= github.com/gorilla/schema v1.2.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM= @@ -65,6 +119,7 @@ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -78,6 +133,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 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/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= @@ -88,25 +144,97 @@ github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdI github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= +golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.181.0 h1:rPdjwnWgiPPOJx3IcSAQ2III5aX5tCer6wMpa/xmZi4= +google.golang.org/api v0.181.0/go.mod h1:MnQ+M0CFsfUwA5beZ+g/vCBCPXvtmZwRz2qzZk8ih1k= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1:mxSlqyb8ZAHsYDCfiXN1EDdNTdvjUJSLY+OnAUtYNYA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= @@ -116,3 +244,5 @@ gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/main b/main index 67e3dc6..bbb6190 100755 Binary files a/main and b/main differ diff --git a/main.go b/main.go old mode 100644 new mode 100755 index 8134a62..306c564 --- a/main.go +++ b/main.go @@ -24,6 +24,7 @@ import ( "jannex/admin-dashboard-backend/modules/systempermissions" "jannex/admin-dashboard-backend/modules/utils" "jannex/admin-dashboard-backend/routers/router" + "jannex/admin-dashboard-backend/routers/router/api/v1/productpipeline" "jannex/admin-dashboard-backend/socketserver" "os" "path/filepath" @@ -91,6 +92,8 @@ INVEX_API_TOKEN=api_token`) grouptasks.InitLoadCategoryGroups() database.InitDatabase() systempermissions.CreateMasterRoleIfNotExist() + + productpipeline.FetchGoogleSheets() } func copySwaggerFolder() { diff --git a/modules/cache/productpipeline.go b/modules/cache/productpipeline.go new file mode 100644 index 0000000..9ca8de9 --- /dev/null +++ b/modules/cache/productpipeline.go @@ -0,0 +1,126 @@ +package cache + +import ( + "jannex/admin-dashboard-backend/modules/structs" + "jannex/admin-dashboard-backend/modules/utils" + "sort" + "sync" + "time" +) + +var pipelineProductsCache *structs.PipelineProductsCache +var pp sync.RWMutex +var pipelineProductsLastUpdated time.Time // last fetch from google sheets +var ppLU sync.RWMutex +var productsStatesCache []structs.ProductState +var ps sync.RWMutex + +func SetPipelineProductsCache(newPipelineProducts structs.PipelineProductsCache) { + pp.Lock() + pipelineProductsCache = &newPipelineProducts + pp.Unlock() +} + +/* +func isPipelineProductCached(name string) bool { + pp.RLock() + defer pp.RUnlock() + + for _, newProduct := range pipelineProductsCache.NewProducts { + if newProduct.Name == name { + return true + } + } + + for _, futureProduct := range pipelineProductsCache.FutureProducts { + if futureProduct.Name == name { + return true + } + } + + for _, inWorkProduct := range pipelineProductsCache.InWorkProducts { + if inWorkProduct == name { + return true + } + } + + return false +} */ + +func IsPipelineProductsCacheTimeExpired() bool { + ppLU.RLock() + defer ppLU.RUnlock() + + return time.Since(pipelineProductsLastUpdated) > utils.ProductPipelineCacheTime +} + +func UpdateProductsPipelineLastCacheUpdate() { + ppLU.Lock() + + pipelineProductsLastUpdated = time.Now() + + ppLU.Unlock() +} + +func GetPipelineProducts() *structs.PipelineProductsCache { + pp.RLock() + defer pp.RUnlock() + + return pipelineProductsCache +} + +func GetProductsStates() []structs.ProductState { + ps.RLock() + defer ps.RUnlock() + + return productsStatesCache +} + +func SetProductStates(productStates []structs.ProductState) { + ps.Lock() + productsStatesCache = productStates + ps.Unlock() +} + +func IsNameInFutureProducts(name string) bool { + pipelineProducts := GetPipelineProducts() + + for _, pipelineProduct := range pipelineProducts.FutureProducts { + if pipelineProduct.Name == name { + return true + } + } + + return false +} + +func VoteFutureProduct(name string, up bool) { + pipelineProducts := GetPipelineProducts() + + for index, futureProduct := range pipelineProducts.FutureProducts { + if futureProduct.Name == name { + pp.Lock() + + if up { + pipelineProductsCache.FutureProducts[index].Votes++ + } else { + + pipelineProductsCache.FutureProducts[index].Votes-- + } + + pp.Unlock() + break + } + } +} + +func SortFutureProducts() { + pipelineProducts := GetPipelineProducts() + + pp.Lock() + defer pp.Unlock() + + sort.SliceStable(pipelineProducts.FutureProducts, func(i, j int) bool { + return pipelineProducts.FutureProducts[i].Votes > pipelineProducts.FutureProducts[j].Votes + }) +} diff --git a/modules/database/database.go b/modules/database/database.go index f61b0bb..a6360d1 100644 --- a/modules/database/database.go +++ b/modules/database/database.go @@ -50,4 +50,5 @@ func InitDatabase() { db.AutoMigrate(&structs.CrmLink{}) db.AutoMigrate(&structs.CrmLinkHistory{}) db.AutoMigrate(&structs.CustomerFeedback{}) + db.AutoMigrate(&structs.PipelineProduct{}) } diff --git a/modules/structs/productpipeline.go b/modules/structs/productpipeline.go new file mode 100644 index 0000000..8027b77 --- /dev/null +++ b/modules/structs/productpipeline.go @@ -0,0 +1,47 @@ +package structs + +// database model +type PipelineProduct struct { + Name string `gorm:"primaryKey"` // name is used as ID + Votes int +} + +type NewProduct struct { + Name string + Url string + Variant string + Characteristics string +} + +type InWorkProduct struct { + Name string + Variant string + Characteristics string +} + +type FutureProduct struct { + Name string + Votes int + Variant string + Characteristics string +} + +type PipelineProductsCache struct { + NewProducts []NewProduct + InWorkProducts []InWorkProduct + FutureProducts []FutureProduct +} + +type ProductState struct { + Status string // like Warteschlange, In Arbeit + State uint8 // like 1, 2, 3 +} + +type VoteProductQuery struct { + /* T = type */ + T string // u = up, d = down +} + +type VoteProductRequest struct { + Name string +} diff --git a/modules/utils/globals.go b/modules/utils/globals.go index d7bd08e..3ced78b 100644 --- a/modules/utils/globals.go +++ b/modules/utils/globals.go @@ -1,5 +1,7 @@ package utils +import "time" + const ( minUsername = "2" maxUsername = "20" @@ -309,3 +311,5 @@ const ( SubscribedTopicCustomerFeedback = "/customer-feedback/" ) + +var ProductPipelineCacheTime = 2 * time.Hour diff --git a/routers/router/api/v1/productpipeline/productpipeline.go b/routers/router/api/v1/productpipeline/productpipeline.go new file mode 100644 index 0000000..1bcf173 --- /dev/null +++ b/routers/router/api/v1/productpipeline/productpipeline.go @@ -0,0 +1,286 @@ +package productpipeline + +import ( + "context" + "errors" + "fmt" + "jannex/admin-dashboard-backend/modules/cache" + "jannex/admin-dashboard-backend/modules/database" + "jannex/admin-dashboard-backend/modules/logger" + "jannex/admin-dashboard-backend/modules/structs" + "strconv" + + "git.ex.umbach.dev/Alex/roese-utils/rslogger" + "git.ex.umbach.dev/Alex/roese-utils/rsutils" + "github.com/gofiber/fiber/v2" + "google.golang.org/api/option" + "google.golang.org/api/sheets/v4" + "gorm.io/gorm" +) + +var ( + serviceAccountFile = "./groupTasks/secrets/shinnex-424321-b88b144bc9ef.json" + spreadsheetId = "1gZkjykb55aLWumBxHxj_ZUq_ktjGK4FlJsH_9qg-ThU" + + // names of worksheets from google sheet + googleWorksheetPipeline = "Pipeline" + googleWorksheetPipelineParameterValues = "Pipeline Parameterwerte" +) + +func GetProducts(c *fiber.Ctx) error { + // fetch from google sheets if cache time expired + if cache.IsPipelineProductsCacheTimeExpired() { + if err := FetchGoogleSheets(); err != nil { + return c.SendStatus(fiber.StatusInternalServerError) + } + } + + return c.JSON(cache.GetPipelineProducts()) +} + +func getGoogleSheetsService() (*sheets.Service, error) { + ctx := context.Background() + + srv, err := sheets.NewService(ctx, option.WithCredentialsFile(serviceAccountFile)) + + if err != nil { + logger.AddSystemLog(rslogger.LogTypeError, "Unable to retrieve Sheets client: %v", err) + return nil, err + } + + return srv, nil +} + +func getStateByStatus(status string) uint8 { + for _, productState := range cache.GetProductsStates() { + if productState.Status == status { + return productState.State + } + } + + return 0 +} + +func FetchGoogleSheets() error { + srv, err := getGoogleSheetsService() + + if err != nil { + logger.AddSystemLog(rslogger.LogTypeError, "Failed to fetch product states") + return err + } + + if err = fetchProductStates(srv); err != nil { + logger.AddSystemLog(rslogger.LogTypeError, "FetchGoogleSheets failed on fetching product states, err: "+err.Error()) + return err + } + + if err = fetchProducts(srv); err != nil { + logger.AddSystemLog(rslogger.LogTypeError, "FetchGoogleSheets failed on fetching products, err: "+err.Error()) + return err + } + + cache.SortFutureProducts() + cache.UpdateProductsPipelineLastCacheUpdate() + + return nil +} + +func fetchProducts(srv *sheets.Service) error { + logger.AddSystemLog(rslogger.LogTypeInfo, "Fetching products from google sheets") + + readRange := googleWorksheetPipeline + resp, err := srv.Spreadsheets.Values.Get(spreadsheetId, readRange).Do() + + if err != nil { + logger.AddSystemLog(rslogger.LogTypeError, "Unable to retrieve data from sheet: %v", err) + return err + } + + // no products found + if len(resp.Values) == 0 { + logger.AddSystemLog(rslogger.LogTypeInfo, "No products found") + return nil + } + + // get products from database + var databasePipelineProducts []structs.PipelineProduct + + database.DB.Find(&databasePipelineProducts) + + // check if there is a new product on google sheets which not exists in database + + var newProducts []structs.NewProduct + var inWorkProducts []structs.InWorkProduct + var futureProducts []structs.FutureProduct + + for _, row := range resp.Values[1:] { // skip first google worksheet row + // skip to next if status or name is empty + if row[0] == "" || row[1] == "" { + continue + } + + status := fmt.Sprintf("%v", row[0]) + name := fmt.Sprintf("%v", row[1]) + + var productVariant string + + if row[2] != "" { + productVariant = fmt.Sprintf("%v", row[2]) + } + + var productCharacteristics string + + if row[3] != "" { + productCharacteristics = fmt.Sprintf("%v", row[3]) + } + + state := getStateByStatus(status) + + // add product to database if not exist + if !isPipelineProductInDatabase(databasePipelineProducts, name) { + database.DB.Create(&structs.PipelineProduct{ + Name: name, + Votes: 0, + }) + } + + // cache product + + if state == 1 { + futureProducts = append(futureProducts, structs.FutureProduct{ + Name: name, + Votes: getVotes(databasePipelineProducts, name), // votes from database + Variant: productVariant, + Characteristics: productCharacteristics, + }) + } else if state == 2 { + inWorkProducts = append(inWorkProducts, structs.InWorkProduct{ + Name: name, + Variant: productVariant, + Characteristics: productCharacteristics, + }) + } else if state == 3 { + var url string + + if row[7] != "" { + url = fmt.Sprintf("%v", row[7]) + } + + newProducts = append(newProducts, structs.NewProduct{ + Name: name, + Url: url, + Variant: productVariant, + Characteristics: productCharacteristics, + }) + } + } + + cache.SetPipelineProductsCache(structs.PipelineProductsCache{ + NewProducts: newProducts, + InWorkProducts: inWorkProducts, + FutureProducts: futureProducts, + }) + + return nil +} + +func getVotes(pipelineProducts []structs.PipelineProduct, name string) int { + for _, pipelineProduct := range pipelineProducts { + if pipelineProduct.Name == name { + return pipelineProduct.Votes + } + } + + return 0 +} + +func fetchProductStates(srv *sheets.Service) error { + logger.AddSystemLog(rslogger.LogTypeInfo, "Fetching product states from google sheets") + + readRange := googleWorksheetPipelineParameterValues + resp, err := srv.Spreadsheets.Values.Get(spreadsheetId, readRange).Do() + + if err != nil { + logger.AddSystemLog(rslogger.LogTypeError, "Unable to retrieve data from sheet: %v", err) + return err + } + + if len(resp.Values) == 0 { + logger.AddSystemLog(rslogger.LogTypeInfo, "No product states found") + return nil + } + + var productStates []structs.ProductState + + for index, row := range resp.Values { + // skip first google sheets row + if index == 0 { + continue + } + + status := fmt.Sprintf("%v", row[0]) + state, err := strconv.ParseUint(fmt.Sprintf("%v", row[1]), 10, 64) + + if err != nil { + return errors.New("Failed to parse uint8, err: " + err.Error()) + } + + productStates = append(productStates, structs.ProductState{ + Status: status, + State: uint8(state), + }) + } + + cache.SetProductStates(productStates) + + return nil +} + +func isPipelineProductInDatabase(pipelineProducts []structs.PipelineProduct, name string) bool { + for _, pipelineProduct := range pipelineProducts { + if pipelineProduct.Name == name { + return true + } + } + return false +} + +func VoteProduct(c *fiber.Ctx) error { + var query structs.VoteProductQuery + + if err := rsutils.QueryParserHelper(c, &query); err != nil { + logger.AddSystemLog(rslogger.LogTypeError, "VoteProduct invalid query, err: %s", err.Error()) + return c.SendStatus(fiber.StatusBadRequest) + } + + if query.T != "u" && query.T != "d" { + return c.SendStatus(fiber.StatusBadRequest) + } + + var body structs.VoteProductRequest + + if err := rsutils.BodyParserHelper(c, &body); err != nil { + logger.AddSystemLog(rslogger.LogTypeError, "VoteProduct invalid body, err: %s", err.Error()) + return c.SendStatus(fiber.StatusBadRequest) + } + + if !cache.IsNameInFutureProducts(body.Name) { + logger.AddSystemLog(rslogger.LogTypeWarning, "VoteProduct invalid product name provided, name: %s", body.Name) + return c.SendStatus(fiber.StatusBadRequest) + } + + operator := "+" + + if query.T == "d" { + operator = "-" + } + + database.DB.Model(&structs.PipelineProduct{}).Where("name = ?", body.Name).Update("votes", gorm.Expr(fmt.Sprintf("votes %s ?", operator), 1)) + + cache.VoteFutureProduct(body.Name, query.T == "u") + cache.SortFutureProducts() + + logger.AddSystemLog(rslogger.LogTypeInfo, "Vote name: %v up vote: %v", body.Name, query.T) + + return c.SendStatus(fiber.StatusOK) +} diff --git a/routers/router/router.go b/routers/router/router.go index 2b8995d..260d9af 100644 --- a/routers/router/router.go +++ b/routers/router/router.go @@ -14,6 +14,7 @@ import ( "jannex/admin-dashboard-backend/routers/router/api/v1/logmanagerserverconnections" "jannex/admin-dashboard-backend/routers/router/api/v1/machines" "jannex/admin-dashboard-backend/routers/router/api/v1/notification" + "jannex/admin-dashboard-backend/routers/router/api/v1/productpipeline" "jannex/admin-dashboard-backend/routers/router/api/v1/user" "jannex/admin-dashboard-backend/routers/router/api/v1/users" "jannex/admin-dashboard-backend/routers/router/api/v1/webhook" @@ -92,6 +93,11 @@ func SetupRoutes(app *fiber.App) { cf.Get("/origin/:origin", requestAccessValidation, customerfeedback.GetCustomerOriginFeedbacks) cf.Get("/origins", requestAccessValidation, customerfeedback.GetCustomerFeedbackOrigins) + pp := v1.Group("/productpipeline") + + pp.Get("/", productpipeline.GetProducts) + pp.Post("/vote", productpipeline.VoteProduct) + app.Static("/", config.Cfg.FolderPaths.PublicStatic) } diff --git a/start.sh b/start.sh index c0aacbb..d250f75 100755 --- a/start.sh +++ b/start.sh @@ -1,2 +1,5 @@ -screen -dmS admin-dashboard-backend | exit 0 -screen -S admin-dashboard-backend -p 0 -X stuff 'go run main.go\n' \ No newline at end of file +#screen -dmS admin-dashboard-backend | exit 0 +#screen -S admin-dashboard-backend -p 0 -X stuff 'go run main.go\n' + +go build main.go +sudo systemctl restart admin-dashboard-backend.service \ No newline at end of file