From 1f410ad3e42a041e605df1b603aa704f7f21d246 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 09:28:46 -0300 Subject: [PATCH 01/74] Initial commit --- backend/go.mod | 3 +++ backend/main.go | 0 2 files changed, 3 insertions(+) create mode 100644 backend/go.mod create mode 100644 backend/main.go diff --git a/backend/go.mod b/backend/go.mod new file mode 100644 index 0000000..daf72e6 --- /dev/null +++ b/backend/go.mod @@ -0,0 +1,3 @@ +module github.com/joaooliveira247/backend-test + +go 1.24.1 diff --git a/backend/main.go b/backend/main.go new file mode 100644 index 0000000..e69de29 From ed21318522b03540840673f43cc96c30ab043cf5 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 09:33:42 -0300 Subject: [PATCH 02/74] chore(git): add .gitignore --- .gitignore | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f36d5dd --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work +go.work.sum + +# env file +.env + +# tmp files +tmp/ + +#React gitignore + +.idea/ +.vscode/ +node_modules/ +build +.DS_Store +*.tgz +my-app* +template/src/__tests__/__snapshots__/ +lerna-debug.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +/.changelog +.npm/ +yarn.lock \ No newline at end of file From fffbd095a3c7b692ad0b8d660fa6cdcf5aaff48e Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 09:48:06 -0300 Subject: [PATCH 03/74] chore(package): add gorm.io/gorm --- backend/go.mod | 7 +++++++ backend/go.sum | 8 ++++++++ 2 files changed, 15 insertions(+) create mode 100644 backend/go.sum diff --git a/backend/go.mod b/backend/go.mod index daf72e6..09dd8ac 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -1,3 +1,10 @@ module github.com/joaooliveira247/backend-test go 1.24.1 + +require ( + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + golang.org/x/text v0.23.0 // indirect + gorm.io/gorm v1.25.12 // indirect +) diff --git a/backend/go.sum b/backend/go.sum new file mode 100644 index 0000000..6f6d9c6 --- /dev/null +++ b/backend/go.sum @@ -0,0 +1,8 @@ +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= +gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= From 732c065d79f9be5744855fcc2c5db699804f5f86 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 09:49:03 -0300 Subject: [PATCH 04/74] chore(package): add gorm.io/driver/postgres --- backend/go.mod | 7 +++++++ backend/go.sum | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/backend/go.mod b/backend/go.mod index 09dd8ac..098968d 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -3,8 +3,15 @@ module github.com/joaooliveira247/backend-test go 1.24.1 require ( + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/pgx/v5 v5.7.4 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect + golang.org/x/crypto v0.36.0 // indirect + golang.org/x/sync v0.12.0 // indirect golang.org/x/text v0.23.0 // indirect + gorm.io/driver/postgres v1.5.11 // indirect gorm.io/gorm v1.25.12 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index 6f6d9c6..2aa1a5d 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -1,8 +1,29 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.7.4 h1:9wKznZrhWa2QiHL+NjTSPP6yjl3451BX3imWDnokYlg= +github.com/jackc/pgx/v5 v5.7.4/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +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= +gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314= +gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI= gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= From 15b3492ab2927ba005c92e04ca11810ae4240507 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 11:26:38 -0300 Subject: [PATCH 05/74] chore(package): add github.com/google/uuid --- backend/go.mod | 1 + backend/go.sum | 2 ++ 2 files changed, 3 insertions(+) diff --git a/backend/go.mod b/backend/go.mod index 098968d..4461f3b 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -3,6 +3,7 @@ module github.com/joaooliveira247/backend-test go 1.24.1 require ( + github.com/google/uuid v1.6.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgx/v5 v5.7.4 // indirect diff --git a/backend/go.sum b/backend/go.sum index 2aa1a5d..acc0b7d 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -1,4 +1,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= From 995dc79114815c91f0e5517ce455122de8e32bdb Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 11:28:01 -0300 Subject: [PATCH 06/74] chore(package): add github.com/gin-gonic/gin --- backend/go.mod | 25 +++++++++++++++++++ backend/go.sum | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/backend/go.mod b/backend/go.mod index 4461f3b..e7a4afe 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -3,6 +3,17 @@ module github.com/joaooliveira247/backend-test go 1.24.1 require ( + github.com/bytedance/sonic v1.13.2 // indirect + github.com/bytedance/sonic/loader v0.2.4 // indirect + github.com/cloudwego/base64x v0.1.5 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gin-contrib/sse v1.0.0 // indirect + github.com/gin-gonic/gin v1.10.0 // 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.25.0 // indirect + github.com/goccy/go-json v0.10.5 // indirect github.com/google/uuid v1.6.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect @@ -10,9 +21,23 @@ require ( github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.10 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + golang.org/x/arch v0.15.0 // indirect golang.org/x/crypto v0.36.0 // indirect + golang.org/x/net v0.37.0 // indirect golang.org/x/sync v0.12.0 // indirect + golang.org/x/sys v0.31.0 // indirect golang.org/x/text v0.23.0 // indirect + google.golang.org/protobuf v1.36.6 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect gorm.io/driver/postgres v1.5.11 // indirect gorm.io/gorm v1.25.12 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index acc0b7d..cdc227f 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -1,4 +1,29 @@ +github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= +github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= +github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= +github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= +github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= +github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E= +github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8= +github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= +github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= +github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -13,19 +38,61 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= +github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 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.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw= +golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= 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= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314= gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI= gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= From 05e60723f55aaecb329c1f6b893afb4c82fe19ea Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 17:03:43 -0300 Subject: [PATCH 07/74] feat(config): add DATABASE_URL for database connection --- backend/src/config/config.go | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 backend/src/config/config.go diff --git a/backend/src/config/config.go b/backend/src/config/config.go new file mode 100644 index 0000000..bdad1b4 --- /dev/null +++ b/backend/src/config/config.go @@ -0,0 +1,5 @@ +package config + +var ( + DATABASE_URL = "" +) From ba8c56e859da057bf34231d0162b365eb92da4bf Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 17:05:13 -0300 Subject: [PATCH 08/74] feat(config): add LoadEnv func to get DATABASE_URL from env --- backend/src/config/config.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/src/config/config.go b/backend/src/config/config.go index bdad1b4..b2ccfa8 100644 --- a/backend/src/config/config.go +++ b/backend/src/config/config.go @@ -1,5 +1,11 @@ package config +import "os" + var ( DATABASE_URL = "" ) + +func LoadEnv() { + DATABASE_URL = os.Getenv("DATABASE_URL") +} From 811b341a62ef63524ded001799df80c2452bb875 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 17:10:09 -0300 Subject: [PATCH 09/74] feat(models): add BaseModel struct --- backend/src/models/models.go | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 backend/src/models/models.go diff --git a/backend/src/models/models.go b/backend/src/models/models.go new file mode 100644 index 0000000..8f7fc96 --- /dev/null +++ b/backend/src/models/models.go @@ -0,0 +1,8 @@ +package models + +import "github.com/google/uuid" + +type BaseModel struct { + ID uuid.UUID `json:"id" gorm:"primaryKey;type:uuid;default:gen_random_uuid()"` + CreatedAt int64 `json:"createdAt" gorm:"autoCreateTime"` +} From 8f39e920d768aa6b36e771c9430d7a3f94727de7 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 17:11:27 -0300 Subject: [PATCH 10/74] feat(models): add UsersModel struct --- backend/src/models/users.go | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 backend/src/models/users.go diff --git a/backend/src/models/users.go b/backend/src/models/users.go new file mode 100644 index 0000000..54ad3e2 --- /dev/null +++ b/backend/src/models/users.go @@ -0,0 +1,9 @@ +package models + +type Users struct { + BaseModel + Name string `json:"name" binding:"required,gt=1,lt=256" gorm:"type:varchar(255);not null;column:name"` + Email string `json:"email" binding:"required,gt=4,lt=256" gorm:"type:varchar(255);unique;not null;column:email"` + Phone string `json:"phone" binding:"required,gt=7,lt=16" gorm:"type:varchar(16);not null;column:phone"` + AffiliateCode string `json:"-" gorm:"type:varchar(8);unique;not null;column:affiliate_code"` +} From 1613d0ef5f59145acc9c5cc4dda82070a211455f Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 17:13:28 -0300 Subject: [PATCH 11/74] feat(models): add Users Validate method to custom validation of email and phone --- backend/src/models/users.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/backend/src/models/users.go b/backend/src/models/users.go index 54ad3e2..c19e1f6 100644 --- a/backend/src/models/users.go +++ b/backend/src/models/users.go @@ -1,5 +1,11 @@ package models +import ( + "errors" + + "github.com/joaooliveira247/backend-test/src/utils" +) + type Users struct { BaseModel Name string `json:"name" binding:"required,gt=1,lt=256" gorm:"type:varchar(255);not null;column:name"` @@ -7,3 +13,12 @@ type Users struct { Phone string `json:"phone" binding:"required,gt=7,lt=16" gorm:"type:varchar(16);not null;column:phone"` AffiliateCode string `json:"-" gorm:"type:varchar(8);unique;not null;column:affiliate_code"` } + +func (user *Users) Validate() error { + if !utils.EmailValidator(user.Email) { + return errors.New("invalid email format") + } else if !utils.IsPhoneNumber(user.Phone) { + return errors.New("invalid phone format") + } + return nil +} From a85b71c04212a2d3f8986d7c5cac68093d0b5e03 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 17:14:31 -0300 Subject: [PATCH 12/74] feat(db): add GetDbConnection func --- backend/src/db/db.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 backend/src/db/db.go diff --git a/backend/src/db/db.go b/backend/src/db/db.go new file mode 100644 index 0000000..e8715dd --- /dev/null +++ b/backend/src/db/db.go @@ -0,0 +1,20 @@ +package db + +import ( + "github.com/joaooliveira247/backend-test/src/config" + "gorm.io/driver/postgres" + "gorm.io/gorm" + "gorm.io/gorm/logger" +) + +func GetDBConnection() (*gorm.DB, error) { + db, err := gorm.Open( + postgres.Open(config.DATABASE_URL), + &gorm.Config{Logger: logger.Default.LogMode(logger.Info)}, + ) + + if err != nil { + return nil, err + } + return db, nil +} From 12b249765391422cd81130e65bf9747369880b5a Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 17:17:23 -0300 Subject: [PATCH 13/74] feat(repositories): add UsersRepositories struct --- backend/src/repositories/users.go | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 backend/src/repositories/users.go diff --git a/backend/src/repositories/users.go b/backend/src/repositories/users.go new file mode 100644 index 0000000..783a62a --- /dev/null +++ b/backend/src/repositories/users.go @@ -0,0 +1,7 @@ +package repositories + +import "gorm.io/gorm" + +type UsersRepository struct { + db *gorm.DB +} From 7795314978a4d4948fd5096a0487a57cfe810119 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 17:18:15 -0300 Subject: [PATCH 14/74] feat(repositories): add NewUsersRepository func --- backend/src/repositories/users.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/src/repositories/users.go b/backend/src/repositories/users.go index 783a62a..fab8c48 100644 --- a/backend/src/repositories/users.go +++ b/backend/src/repositories/users.go @@ -5,3 +5,7 @@ import "gorm.io/gorm" type UsersRepository struct { db *gorm.DB } + +func NewUsersRepository(db *gorm.DB) UsersRepository { + return UsersRepository{db} +} From a8401fcb52aa61fb81390ce8328c5f4e78c1f93f Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 17:19:10 -0300 Subject: [PATCH 15/74] feat(repositories): add UsersRepository Create method --- backend/src/repositories/users.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/backend/src/repositories/users.go b/backend/src/repositories/users.go index fab8c48..c8adb93 100644 --- a/backend/src/repositories/users.go +++ b/backend/src/repositories/users.go @@ -1,6 +1,9 @@ package repositories -import "gorm.io/gorm" +import ( + "github.com/joaooliveira247/backend-test/src/models" + "gorm.io/gorm" +) type UsersRepository struct { db *gorm.DB @@ -9,3 +12,13 @@ type UsersRepository struct { func NewUsersRepository(db *gorm.DB) UsersRepository { return UsersRepository{db} } + +func (repository *UsersRepository) Create(user *models.Users) (string, error) { + result := repository.db.Create(&user) + + if err := result.Error; err != nil { + return "", err + } + + return user.AffiliateCode, nil +} From 10ec559b997023ea9a69e4bc99772c99cdf61d98 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Wed, 26 Mar 2025 17:21:23 -0300 Subject: [PATCH 16/74] chore(docker): add docker-compose database instace to run project in development local --- docker-compose.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 docker-compose.yaml diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..a56c582 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,17 @@ +version: "3.1" + +services: + carbon_offset_db: + image: postgres:alpine3.20 + restart: "no" + environment: + POSTGRES_USER: user + POSTGRES_PASSWORD: passwd + POSTGRES_DB: carbon_offset + networks: + - carbon_offset_network + ports: + - 5432:5432 + +networks: + carbon_offset_network: \ No newline at end of file From cbe52fa8cf27b4729682d1fc676a292f160c8ada Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 16:53:11 -0300 Subject: [PATCH 17/74] feat(db): add CreateTables func --- backend/src/db/db.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/src/db/db.go b/backend/src/db/db.go index e8715dd..c54f720 100644 --- a/backend/src/db/db.go +++ b/backend/src/db/db.go @@ -2,6 +2,7 @@ package db import ( "github.com/joaooliveira247/backend-test/src/config" + "github.com/joaooliveira247/backend-test/src/models" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" @@ -18,3 +19,10 @@ func GetDBConnection() (*gorm.DB, error) { } return db, nil } + +func CreateTables(db *gorm.DB) error { + if err := db.AutoMigrate(&models.Users{}, &models.Competitions{}, &models.Points{}); err != nil { + return err + } + return nil +} From e47cd949f6b53d41d4f56a57ef849ae582f7b3b3 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 16:54:53 -0300 Subject: [PATCH 18/74] feat(models): add Users IsEmpty method --- backend/src/models/users.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/src/models/users.go b/backend/src/models/users.go index c19e1f6..f5120f3 100644 --- a/backend/src/models/users.go +++ b/backend/src/models/users.go @@ -3,6 +3,7 @@ package models import ( "errors" + "github.com/google/uuid" "github.com/joaooliveira247/backend-test/src/utils" ) @@ -22,3 +23,7 @@ func (user *Users) Validate() error { } return nil } + +func (user *Users) IsEmpty() bool { + return user.ID == uuid.Nil +} From 8c39467488c4193e91b372f69c0827b5e504cb58 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 16:56:20 -0300 Subject: [PATCH 19/74] feat(models): add Points struct model --- backend/src/models/points.go | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 backend/src/models/points.go diff --git a/backend/src/models/points.go b/backend/src/models/points.go new file mode 100644 index 0000000..fb53123 --- /dev/null +++ b/backend/src/models/points.go @@ -0,0 +1,9 @@ +package models + +import "github.com/google/uuid" + +type Points struct { + BaseModel + CompetitionID uuid.UUID + UserID uuid.UUID +} \ No newline at end of file From 9ea129214e6b118471267910da7b4aa4841ad379 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 16:57:15 -0300 Subject: [PATCH 20/74] feat(models): add Competitions struct model --- backend/src/models/competiotions.go | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 backend/src/models/competiotions.go diff --git a/backend/src/models/competiotions.go b/backend/src/models/competiotions.go new file mode 100644 index 0000000..b00c81f --- /dev/null +++ b/backend/src/models/competiotions.go @@ -0,0 +1,6 @@ +package models + +type Competitions struct { + BaseModel + Status bool `json:"status" gorm:"type:boolean;not null;column:status"` +} From 8fc5f8ab60c4f27b2b97a7bd1c76ec67de208fbf Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 16:57:50 -0300 Subject: [PATCH 21/74] feat(models): add Competitions IsEmpty method --- backend/src/models/competiotions.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/src/models/competiotions.go b/backend/src/models/competiotions.go index b00c81f..44b4855 100644 --- a/backend/src/models/competiotions.go +++ b/backend/src/models/competiotions.go @@ -1,6 +1,12 @@ package models +import "github.com/google/uuid" + type Competitions struct { BaseModel Status bool `json:"status" gorm:"type:boolean;not null;column:status"` } + +func (comp *Competitions) IsEmpty() bool { + return comp.ID == uuid.Nil +} From 40f191a8a50e42831945c0269b72cd3bd77b6cb2 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 16:59:49 -0300 Subject: [PATCH 22/74] feat(repositories): add PointsRepositories struct --- backend/src/repositories/points.go | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 backend/src/repositories/points.go diff --git a/backend/src/repositories/points.go b/backend/src/repositories/points.go new file mode 100644 index 0000000..fee5576 --- /dev/null +++ b/backend/src/repositories/points.go @@ -0,0 +1,8 @@ +package repositories + +import "gorm.io/gorm" + + +type PointsRepository struct { + db *gorm.DB +} From c077485b9c67692d41596996ad85a6ec23edcc65 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 17:00:32 -0300 Subject: [PATCH 23/74] feat(repositories): add NewPointsRepository func --- backend/src/repositories/points.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/src/repositories/points.go b/backend/src/repositories/points.go index fee5576..a23306e 100644 --- a/backend/src/repositories/points.go +++ b/backend/src/repositories/points.go @@ -2,7 +2,10 @@ package repositories import "gorm.io/gorm" - type PointsRepository struct { db *gorm.DB } + +func NewPointsRepository(db *gorm.DB) PointsRepository { + return PointsRepository{db} +} From af23e3bdfac1c57c5bbd0ab904a5dec8e5ea3466 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 17:01:31 -0300 Subject: [PATCH 24/74] feat(repositories): add PointsRepository AddPoint method --- backend/src/repositories/points.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/backend/src/repositories/points.go b/backend/src/repositories/points.go index a23306e..1269b2e 100644 --- a/backend/src/repositories/points.go +++ b/backend/src/repositories/points.go @@ -1,6 +1,9 @@ package repositories -import "gorm.io/gorm" +import ( + "github.com/joaooliveira247/backend-test/src/models" + "gorm.io/gorm" +) type PointsRepository struct { db *gorm.DB @@ -9,3 +12,11 @@ type PointsRepository struct { func NewPointsRepository(db *gorm.DB) PointsRepository { return PointsRepository{db} } + +func (repository *PointsRepository) AddPoint(point *models.Points) error { + if err := repository.db.Create(point).Error; err != nil { + return err + } + + return nil +} From 33d2edf8e8ebeac09fffb16490ed308f868c7520 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 17:02:17 -0300 Subject: [PATCH 25/74] feat(repositories): add UsersRepository GetUserByAffiliateCode method --- backend/src/repositories/users.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/backend/src/repositories/users.go b/backend/src/repositories/users.go index c8adb93..abece43 100644 --- a/backend/src/repositories/users.go +++ b/backend/src/repositories/users.go @@ -22,3 +22,15 @@ func (repository *UsersRepository) Create(user *models.Users) (string, error) { return user.AffiliateCode, nil } + +func (repository *UsersRepository) GetUserByAffiliateCode( + code string, +) (models.Users, error) { + var user models.Users + + if err := repository.db.First(&user, "affiliate_code = ?", code).Error; err != nil { + return models.Users{}, err + } + + return user, nil +} From 4e508cbd1482a449c5b027de692eb722d208a98d Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 17:05:11 -0300 Subject: [PATCH 26/74] feat(repositories): add CompetitionsRepository struct --- backend/src/repositories/competitions.go | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 backend/src/repositories/competitions.go diff --git a/backend/src/repositories/competitions.go b/backend/src/repositories/competitions.go new file mode 100644 index 0000000..84671ac --- /dev/null +++ b/backend/src/repositories/competitions.go @@ -0,0 +1,9 @@ +package repositories + +import ( + "gorm.io/gorm" +) + +type CompetitionsRepository struct { + db *gorm.DB +} From ec374fd1045e7d7f8bd7c0f33bde4cc465f88fd4 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 17:05:58 -0300 Subject: [PATCH 27/74] feat(repositories): add NewCompetitionsRepository func --- backend/src/repositories/competitions.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/src/repositories/competitions.go b/backend/src/repositories/competitions.go index 84671ac..7a30c9b 100644 --- a/backend/src/repositories/competitions.go +++ b/backend/src/repositories/competitions.go @@ -7,3 +7,7 @@ import ( type CompetitionsRepository struct { db *gorm.DB } + +func NewCompetiotionsRepository(db *gorm.DB) CompetitionsRepository { + return CompetitionsRepository{db} +} From b02c4ed554cf82b9c93003ffc076bf4a207bfc2b Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 17:07:16 -0300 Subject: [PATCH 28/74] feat(repositories): add CompetitionsRepository Create method --- backend/src/repositories/competitions.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/backend/src/repositories/competitions.go b/backend/src/repositories/competitions.go index 7a30c9b..49267f1 100644 --- a/backend/src/repositories/competitions.go +++ b/backend/src/repositories/competitions.go @@ -1,6 +1,8 @@ package repositories import ( + "github.com/google/uuid" + "github.com/joaooliveira247/backend-test/src/models" "gorm.io/gorm" ) @@ -11,3 +13,15 @@ type CompetitionsRepository struct { func NewCompetiotionsRepository(db *gorm.DB) CompetitionsRepository { return CompetitionsRepository{db} } + +func (repository *CompetitionsRepository) Create( + competiotion *models.Competitions, +) (uuid.UUID, error) { + result := repository.db.Create(&competiotion) + + if err := result.Error; err != nil { + return uuid.UUID{}, err + } + + return competiotion.ID, nil +} \ No newline at end of file From cef17a903109298fa87a6a0bf2ec5da5df6594e3 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 17:07:59 -0300 Subject: [PATCH 29/74] feat(repositories): add CompetitionsRepository GetActiveCompetition method --- backend/src/repositories/competitions.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/backend/src/repositories/competitions.go b/backend/src/repositories/competitions.go index 49267f1..f0a3735 100644 --- a/backend/src/repositories/competitions.go +++ b/backend/src/repositories/competitions.go @@ -24,4 +24,14 @@ func (repository *CompetitionsRepository) Create( } return competiotion.ID, nil -} \ No newline at end of file +} + +func (repository *CompetitionsRepository) GetActiveCompetition() (models.Competitions, error) { + var competition models.Competitions + + if err := repository.db.First(&competition, "status = true").Error; err != nil { + return models.Competitions{}, err + } + + return competition, nil +} From 84a210623633ff5c721164917dacc0632f6fd5c0 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 17:08:31 -0300 Subject: [PATCH 30/74] feat(repositories): add CompetitionsRepository CloseCompetition method --- backend/src/repositories/competitions.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/backend/src/repositories/competitions.go b/backend/src/repositories/competitions.go index f0a3735..d1b8a0b 100644 --- a/backend/src/repositories/competitions.go +++ b/backend/src/repositories/competitions.go @@ -35,3 +35,21 @@ func (repository *CompetitionsRepository) GetActiveCompetition() (models.Competi return competition, nil } + +func (repository *CompetitionsRepository) CloseCompetition( + competitionID uuid.UUID, +) error { + var competition models.Competitions + + if err := repository.db.First(&competition, "id = ?", competitionID).Error; err != nil { + return err + } + + competition.Status = false + + if err := repository.db.Save(&competition).Error; err != nil { + return err + } + + return nil +} \ No newline at end of file From 67ad2b2abfd86d8fb4c13cc4e83ab774fd5aed19 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:27:54 -0300 Subject: [PATCH 31/74] feat(controllers): add UsersControllers struct --- backend/src/controllers/users.go | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 backend/src/controllers/users.go diff --git a/backend/src/controllers/users.go b/backend/src/controllers/users.go new file mode 100644 index 0000000..779a778 --- /dev/null +++ b/backend/src/controllers/users.go @@ -0,0 +1,11 @@ +package controllers + +import ( + "github.com/joaooliveira247/backend-test/src/repositories" +) + +type UsersController struct { + userRepository repositories.UsersRepository + competitionRepository repositories.CompetitionsRepository + pointRepository repositories.PointsRepository +} From 1f0683cba2c64004db8b36b8c6bfc268a21ab72e Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:29:02 -0300 Subject: [PATCH 32/74] feat(controllers): add NewUsersController func --- backend/src/controllers/users.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/src/controllers/users.go b/backend/src/controllers/users.go index 779a778..64c0bf6 100644 --- a/backend/src/controllers/users.go +++ b/backend/src/controllers/users.go @@ -9,3 +9,11 @@ type UsersController struct { competitionRepository repositories.CompetitionsRepository pointRepository repositories.PointsRepository } + +func NewUsersController( + userRepo repositories.UsersRepository, + compRepo repositories.CompetitionsRepository, + pointRepo repositories.PointsRepository, +) *UsersController { + return &UsersController{userRepo, compRepo, pointRepo} +} \ No newline at end of file From 9f0ac7dcdf9678839dedd5cc449b00459032bdf1 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:31:06 -0300 Subject: [PATCH 33/74] feat(controllers): add UsersController Create method --- backend/src/controllers/users.go | 60 ++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/backend/src/controllers/users.go b/backend/src/controllers/users.go index 64c0bf6..be4ef9f 100644 --- a/backend/src/controllers/users.go +++ b/backend/src/controllers/users.go @@ -1,7 +1,12 @@ package controllers import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/joaooliveira247/backend-test/src/models" "github.com/joaooliveira247/backend-test/src/repositories" + "github.com/joaooliveira247/backend-test/src/utils" ) type UsersController struct { @@ -16,4 +21,59 @@ func NewUsersController( pointRepo repositories.PointsRepository, ) *UsersController { return &UsersController{userRepo, compRepo, pointRepo} +} + +func (ctrl *UsersController) CreateUser(ctx *gin.Context) { + var user models.Users + + if err := ctx.ShouldBindJSON(&user); err != nil { + ctx.JSON( + http.StatusBadRequest, + gin.H{"error": "invalid request body", "details": err.Error()}, + ) + return + } + + if err := user.Validate(); err != nil { + ctx.JSON( + http.StatusBadRequest, + gin.H{"error": "invalid request body", "details": err.Error()}, + ) + return + } + + code, err := utils.GenerateAffiliateCode() + + if err != nil { + ctx.JSON( + http.StatusInternalServerError, + gin.H{ + "error": "error when try create affiliate code", + "details": err.Error(), + }, + ) + return + } + + user.AffiliateCode = code + + affiliateCode, err := ctrl.userRepository.Create(&user) + + if err != nil { + ctx.JSON( + http.StatusInternalServerError, + gin.H{"error": "database error", "details": err.Error()}, + ) + return + } + + comp, _ := ctrl.competitionRepository.GetActiveCompetition() + + if !comp.IsEmpty() { + ctrl.pointRepository.AddPoint( + &models.Points{UserID: user.ID, CompetitionID: comp.ID}, + ) + } + + ctx.JSON(http.StatusCreated, gin.H{"affiliateCode": affiliateCode}) } \ No newline at end of file From 46611877cd0eaaeb2b933ae3bd9cfcc383d7c04c Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:32:13 -0300 Subject: [PATCH 34/74] feat(utils): add GenerateAffiliateCode func --- backend/src/utils/utils.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 backend/src/utils/utils.go diff --git a/backend/src/utils/utils.go b/backend/src/utils/utils.go new file mode 100644 index 0000000..e938522 --- /dev/null +++ b/backend/src/utils/utils.go @@ -0,0 +1,21 @@ +package utils + +import ( + "crypto/rand" + "math/big" +) + +const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + +func GenerateAffiliateCode() (string, error) { + code := make([]byte, 8) + for i := range code { + n, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset)))) + if err != nil { + return "", err + } + code[i] = charset[n.Int64()] + } + + return string(code), nil +} From 4c5c806b717a62de5fb2d37b7bab49b48524a7a4 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:33:06 -0300 Subject: [PATCH 35/74] feat(utils): add EmailValidator func --- backend/src/utils/validators.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 backend/src/utils/validators.go diff --git a/backend/src/utils/validators.go b/backend/src/utils/validators.go new file mode 100644 index 0000000..d180a13 --- /dev/null +++ b/backend/src/utils/validators.go @@ -0,0 +1,22 @@ +package utils + +import ( + "net" + "regexp" + "strings" +) + +func EmailValidator(email string) bool { + regex := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$` + re := regexp.MustCompile(regex) + if !re.MatchString(email) { + return false + } + + parts := strings.Split(email, "@") + if len(parts) != 2 { + return false + } + mxRecords, err := net.LookupMX(parts[1]) + return err == nil && len(mxRecords) > 0 +} From 46c8b8a2a9b58558b6ffe8b2cf629587ffe27e35 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:33:33 -0300 Subject: [PATCH 36/74] feat(utils): add IsPhoneNumber func --- backend/src/utils/validators.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/src/utils/validators.go b/backend/src/utils/validators.go index d180a13..d90cb5d 100644 --- a/backend/src/utils/validators.go +++ b/backend/src/utils/validators.go @@ -20,3 +20,9 @@ func EmailValidator(email string) bool { mxRecords, err := net.LookupMX(parts[1]) return err == nil && len(mxRecords) > 0 } + +func IsPhoneNumber(phone string) bool { + re := regexp.MustCompile(`^\+55\d{11}$`) + + return re.MatchString(phone) +} From c782431408ebc7aeffb31a21845ee6ac5a0c27ef Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:35:21 -0300 Subject: [PATCH 37/74] feat(controllers): add CompetitionsControllers struct --- backend/src/controllers/competitions.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 backend/src/controllers/competitions.go diff --git a/backend/src/controllers/competitions.go b/backend/src/controllers/competitions.go new file mode 100644 index 0000000..0197b0a --- /dev/null +++ b/backend/src/controllers/competitions.go @@ -0,0 +1,12 @@ +package controllers + +import ( + "github.com/joaooliveira247/backend-test/src/repositories" +) + +type CompetitionsController struct { + UserRepository repositories.UsersRepository + CompetitionRepository repositories.CompetitionsRepository + PointRepository repositories.PointsRepository +} + From ff1fcd5e168697a786d4eaa7dc51ed6acd51877a Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:36:31 -0300 Subject: [PATCH 38/74] feat(controllers): add NewCompetitionsController func --- backend/src/controllers/competitions.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backend/src/controllers/competitions.go b/backend/src/controllers/competitions.go index 0197b0a..10ab1f8 100644 --- a/backend/src/controllers/competitions.go +++ b/backend/src/controllers/competitions.go @@ -10,3 +10,10 @@ type CompetitionsController struct { PointRepository repositories.PointsRepository } +func NewCompetitionsController( + userRepo repositories.UsersRepository, + compRepo repositories.CompetitionsRepository, + pointRepo repositories.PointsRepository, +) *CompetitionsController { + return &CompetitionsController{userRepo, compRepo, pointRepo} +} From 60c62a991983fe63a4513dc38bb0d8270f1a3de1 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:38:08 -0300 Subject: [PATCH 39/74] feat(controllers): add CompetitionsController Create method --- backend/src/controllers/competitions.go | 32 +++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/backend/src/controllers/competitions.go b/backend/src/controllers/competitions.go index 10ab1f8..167f7b7 100644 --- a/backend/src/controllers/competitions.go +++ b/backend/src/controllers/competitions.go @@ -1,6 +1,10 @@ package controllers import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/joaooliveira247/backend-test/src/models" "github.com/joaooliveira247/backend-test/src/repositories" ) @@ -17,3 +21,31 @@ func NewCompetitionsController( ) *CompetitionsController { return &CompetitionsController{userRepo, compRepo, pointRepo} } + +func (ctrl *CompetitionsController) Create(ctx *gin.Context) { + compCheck, _ := ctrl.CompetitionRepository.GetActiveCompetition() + + if compCheck.IsEmpty() { + id, err := ctrl.CompetitionRepository.Create( + &models.Competitions{Status: true}, + ) + + if err != nil { + ctx.JSON( + http.StatusInternalServerError, + gin.H{"error": "create competition", "details": err.Error()}, + ) + return + } + ctx.JSON(http.StatusCreated, gin.H{"id": id}) + return + } + + ctx.JSON( + http.StatusConflict, + gin.H{ + "error": "competition already activated", + "details": compCheck.ID, + }, + ) +} From 05b1f7f85b3ac6d081a57eb8ec36e3d1c65843b8 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:39:00 -0300 Subject: [PATCH 40/74] feat(controllers): add CompetitionsController GetCompetition method --- backend/src/controllers/competitions.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/backend/src/controllers/competitions.go b/backend/src/controllers/competitions.go index 167f7b7..f20ede0 100644 --- a/backend/src/controllers/competitions.go +++ b/backend/src/controllers/competitions.go @@ -49,3 +49,26 @@ func (ctrl *CompetitionsController) Create(ctx *gin.Context) { }, ) } + +func (ctrl *CompetitionsController) GetCompetition(ctx *gin.Context) { + // main request for main screen + compCheck, _ := ctrl.CompetitionRepository.GetActiveCompetition() + + if !compCheck.IsEmpty() { + if code := ctx.Query("affiliateCode"); code != "" { + user, _ := ctrl.UserRepository.GetUserByAffiliateCode(code) + + if !user.IsEmpty() { + ctrl.PointRepository.AddPoint( + &models.Points{ + UserID: user.ID, + CompetitionID: compCheck.ID, + }, + ) + } + } + ctx.JSON(http.StatusOK, compCheck) + return + } + ctx.JSON(http.StatusNoContent, nil) +} From 0598df052154febb983f410ada99ea27ae3a1e5a Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:42:36 -0300 Subject: [PATCH 41/74] feat(controllers): add CompetitionsController CloseCompetition method --- backend/src/controllers/competitions.go | 36 +++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/backend/src/controllers/competitions.go b/backend/src/controllers/competitions.go index f20ede0..d6d8d2b 100644 --- a/backend/src/controllers/competitions.go +++ b/backend/src/controllers/competitions.go @@ -1,11 +1,14 @@ package controllers import ( + "errors" "net/http" "github.com/gin-gonic/gin" + "github.com/google/uuid" "github.com/joaooliveira247/backend-test/src/models" "github.com/joaooliveira247/backend-test/src/repositories" + "gorm.io/gorm" ) type CompetitionsController struct { @@ -72,3 +75,36 @@ func (ctrl *CompetitionsController) GetCompetition(ctx *gin.Context) { } ctx.JSON(http.StatusNoContent, nil) } + +func (ctrl *CompetitionsController) CloseCompetition(ctx *gin.Context) { + compID, err := uuid.Parse(ctx.Query("ID")) + + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{ + "error": "invalid id format", "details": err.Error(), + }) + return + } + + if err := ctrl.CompetitionRepository.CloseCompetition(compID); err != nil { + + if errors.Is(err, gorm.ErrRecordNotFound) { + ctx.JSON( + http.StatusNotFound, + gin.H{ + "error": "competition not found", + "details": err.Error(), + }, + ) + return + } + + ctx.JSON( + http.StatusInternalServerError, + gin.H{"error": "closed competition error", "details": err.Error()}, + ) + return + } + + ctx.JSON(http.StatusNoContent, nil) +} From 7c58e556b7f39cc651111d96958abcbeb6f105d9 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:43:51 -0300 Subject: [PATCH 42/74] feat(routes): add UsersRoute func --- backend/src/routes/users.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 backend/src/routes/users.go diff --git a/backend/src/routes/users.go b/backend/src/routes/users.go new file mode 100644 index 0000000..0c11df8 --- /dev/null +++ b/backend/src/routes/users.go @@ -0,0 +1,33 @@ +package routes + +import ( + "log" + + "github.com/gin-gonic/gin" + "github.com/joaooliveira247/backend-test/src/controllers" + "github.com/joaooliveira247/backend-test/src/db" + "github.com/joaooliveira247/backend-test/src/repositories" +) + +func UsersRoute(eng *gin.Engine) { + gormDB, err := db.GetDBConnection() + + if err != nil { + log.Fatalf("Users Route: %v", err) + } + + usersReposiotry := repositories.NewUsersRepository(gormDB) + compsRepository := repositories.NewCompetiotionsRepository(gormDB) + pointsRepository := repositories.NewPointsRepository(gormDB) + + controller := controllers.NewUsersController( + usersReposiotry, + compsRepository, + pointsRepository, + ) + + usersGroup := eng.Group("/users") + { + usersGroup.POST("/", controller.CreateUser) + } +} From ebbab655f00114637085d59d6f9ddcce4ef108fb Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:44:34 -0300 Subject: [PATCH 43/74] feat(routes): add CompetitionsRoute func --- backend/src/routes/competitions.go | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 backend/src/routes/competitions.go diff --git a/backend/src/routes/competitions.go b/backend/src/routes/competitions.go new file mode 100644 index 0000000..48bf180 --- /dev/null +++ b/backend/src/routes/competitions.go @@ -0,0 +1,35 @@ +package routes + +import ( + "log" + + "github.com/gin-gonic/gin" + "github.com/joaooliveira247/backend-test/src/controllers" + "github.com/joaooliveira247/backend-test/src/db" + "github.com/joaooliveira247/backend-test/src/repositories" +) + +func CompetitionsRoute(eng *gin.Engine) { + gormDB, err := db.GetDBConnection() + + if err != nil { + log.Fatalf("Users Route: %v", err) + } + + usersReposiotry := repositories.NewUsersRepository(gormDB) + compsRepository := repositories.NewCompetiotionsRepository(gormDB) + pointsRepository := repositories.NewPointsRepository(gormDB) + + controller := controllers.NewCompetitionsController( + usersReposiotry, + compsRepository, + pointsRepository, + ) + + competitionsGroup := eng.Group("/competitions") + { + competitionsGroup.POST("/", controller.Create) + competitionsGroup.GET("/", controller.GetCompetition) + competitionsGroup.PUT("/", controller.CloseCompetition) + } +} \ No newline at end of file From 496a30e04d0b085a89338622fb851c8b2d279fb6 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:45:36 -0300 Subject: [PATCH 44/74] feat(routes): add RegistryRoutes func --- backend/src/routes/routes.go | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 backend/src/routes/routes.go diff --git a/backend/src/routes/routes.go b/backend/src/routes/routes.go new file mode 100644 index 0000000..9049193 --- /dev/null +++ b/backend/src/routes/routes.go @@ -0,0 +1,8 @@ +package routes + +import "github.com/gin-gonic/gin" + +func RegistryRoutes(eng *gin.Engine) { + UsersRoute(eng) + CompetitionsRoute(eng) +} From 6609544fde173a9bc16cfebe419ab9e97635a6af Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:48:23 -0300 Subject: [PATCH 45/74] chore(docker) add docker file with air to run project --- backend/Dockerfile | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 backend/Dockerfile diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..33a9ec2 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,10 @@ +FROM golang:1.24.1-alpine3.21 + +WORKDIR /app + +RUN go install github.com/air-verse/air@latest + +COPY . . +RUN go mod download + +CMD ["air", "run"] \ No newline at end of file From b3285452f38ab18c67b61acff23d0265e83a104a Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:49:32 -0300 Subject: [PATCH 46/74] feat(main) add init func to load env --- backend/main.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/backend/main.go b/backend/main.go index e69de29..8d69a31 100644 --- a/backend/main.go +++ b/backend/main.go @@ -0,0 +1,9 @@ +package main + +import ( + "github.com/joaooliveira247/backend-test/src/config" +) + +func init() { + config.LoadEnv() +} From fc19e4c0b103730b6c2947b3a36f5900a813f644 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:50:25 -0300 Subject: [PATCH 47/74] feat(main) add main func to run project --- backend/main.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/backend/main.go b/backend/main.go index 8d69a31..b94d0cd 100644 --- a/backend/main.go +++ b/backend/main.go @@ -1,9 +1,35 @@ package main import ( + "log" + + "github.com/gin-gonic/gin" "github.com/joaooliveira247/backend-test/src/config" + "github.com/joaooliveira247/backend-test/src/db" + "github.com/joaooliveira247/backend-test/src/routes" ) func init() { config.LoadEnv() } + +func main() { + + gormDB, err := db.GetDBConnection() + + if err != nil { + log.Fatalf("DATABASE Connection: %v", err) + } + + if err := db.CreateTables(gormDB); err != nil { + log.Fatalf("DATABASE Tables Creation: %v", err) + return + } + + api := gin.Default() + routes.RegistryRoutes(api) + + if err := api.Run(":8000"); err != nil { + log.Fatalf("API RUN: err") + } +} From 69e948a7121ce4a3994f03c680091dc6c04d9180 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Thu, 27 Mar 2025 19:51:25 -0300 Subject: [PATCH 48/74] chore(docker) add container instace to run api --- docker-compose.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docker-compose.yaml b/docker-compose.yaml index a56c582..b8db3c4 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,6 +1,19 @@ version: "3.1" services: + carbon_offset_api: + build: + context: ./backend + dockerfile: Dockerfile + environment: + - DATABASE_URL= host=carbon_offset_db user=user password=passwd dbname=carbon_offset port=5432 sslmode=disable + networks: + - carbon_offset_network + ports: + - 8000:8000 + volumes: + - ./backend:/app + carbon_offset_db: image: postgres:alpine3.20 restart: "no" From 00e519ed42092e054cb1a0bcb86057114bdf1f0f Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 10:24:04 -0300 Subject: [PATCH 49/74] fix(models) add Points model CompetitionID and userID gorm field tags --- backend/src/models/points.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/models/points.go b/backend/src/models/points.go index fb53123..fd7f0e9 100644 --- a/backend/src/models/points.go +++ b/backend/src/models/points.go @@ -4,6 +4,6 @@ import "github.com/google/uuid" type Points struct { BaseModel - CompetitionID uuid.UUID - UserID uuid.UUID + CompetitionID uuid.UUID `gorm:"type:uuid;column:competition_id"` + UserID uuid.UUID `gorm:"type:uuid;column:user_id"` } \ No newline at end of file From bd74a01772b3f1884645331f5a78a8da30f9298f Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 10:24:50 -0300 Subject: [PATCH 50/74] feat(models) add CompetitionReport model --- backend/src/models/competiotions.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backend/src/models/competiotions.go b/backend/src/models/competiotions.go index 44b4855..6c061ef 100644 --- a/backend/src/models/competiotions.go +++ b/backend/src/models/competiotions.go @@ -7,6 +7,13 @@ type Competitions struct { Status bool `json:"status" gorm:"type:boolean;not null;column:status"` } +type CompetitionReport struct { + Name string `json:"name" gorm:"column:name"` + Points uint64 `json:"points" gorm:"column:points"` + Email string `json:"-" gorm:"column:email"` + Phone string `json:"-" gorm:"column:phone"` +} + func (comp *Competitions) IsEmpty() bool { return comp.ID == uuid.Nil } From 09948eec607e2118c40dcf88034f878998285268 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 10:25:53 -0300 Subject: [PATCH 51/74] feat(controllers): add CompetitionsController GetCompetitionReport method --- backend/src/repositories/competitions.go | 28 +++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/backend/src/repositories/competitions.go b/backend/src/repositories/competitions.go index d1b8a0b..b68c6b7 100644 --- a/backend/src/repositories/competitions.go +++ b/backend/src/repositories/competitions.go @@ -52,4 +52,30 @@ func (repository *CompetitionsRepository) CloseCompetition( } return nil -} \ No newline at end of file +} + +func (repository *CompetitionsRepository) GetCompetitionReport( + competitionID uuid.UUID, +) ([]models.CompetitionReport, error) { + rawQuery := ` +SELECT + u.name, + u.email, + u.phone, + COUNT(*) AS points +FROM points p +INNER JOIN users u ON p.user_id = u.id +WHERE p.competition_id = ? +GROUP BY u.name, u.email, u.phone +ORDER BY points DESC +LIMIT 10; + ` + + var reports []models.CompetitionReport + + if err := repository.db.Raw(rawQuery, competitionID).Scan(&reports).Error; err != nil { + return nil, err + } + + return reports, nil +} From 305072afaa07ffae81725f000ed653c1103f2b96 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 10:26:50 -0300 Subject: [PATCH 52/74] feat(repositories): add CompetitionsRepository GetCompetitionByID method --- backend/src/repositories/competitions.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/backend/src/repositories/competitions.go b/backend/src/repositories/competitions.go index b68c6b7..476ca8d 100644 --- a/backend/src/repositories/competitions.go +++ b/backend/src/repositories/competitions.go @@ -36,6 +36,16 @@ func (repository *CompetitionsRepository) GetActiveCompetition() (models.Competi return competition, nil } +func (repository *CompetitionsRepository) GetCompetitionByID(competitionID uuid.UUID) (models.Competitions, error) { + var competition models.Competitions + + if err := repository.db.First(&competition, "id = ?", competitionID).Error; err != nil { + return models.Competitions{}, err + } + + return competition, nil +} + func (repository *CompetitionsRepository) CloseCompetition( competitionID uuid.UUID, ) error { From 994b523db0ea19ced3af721ceb358065a42267b6 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 10:27:37 -0300 Subject: [PATCH 53/74] feat(controllers): add CompetitionsController GetCompetitionReport method --- backend/src/controllers/competitions.go | 34 +++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/backend/src/controllers/competitions.go b/backend/src/controllers/competitions.go index d6d8d2b..6ca5a99 100644 --- a/backend/src/controllers/competitions.go +++ b/backend/src/controllers/competitions.go @@ -108,3 +108,37 @@ func (ctrl *CompetitionsController) CloseCompetition(ctx *gin.Context) { ctx.JSON(http.StatusNoContent, nil) } + +func (ctrl *CompetitionsController) GetCompetitionReport(ctx *gin.Context) { + compID, err := uuid.Parse(ctx.Query("ID")) + + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{ + "error": "invalid id format", "details": err.Error(), + }) + return + } + + comp, _ := ctrl.CompetitionRepository.GetCompetitionByID(compID) + + if comp.Status { + ctx.JSON(http.StatusConflict, gin.H{"error": "competition not closed"}) + return + } + + reports, err := ctrl.CompetitionRepository.GetCompetitionReport(compID) + + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{ + "error": "gen competition report", "details": err.Error(), + }) + return + } + + if reports == nil { + ctx.JSON(http.StatusNotFound, gin.H{"error": "competiton not found"}) + return + } + + ctx.JSON(http.StatusOK, reports) +} From b94e79477a17bd219a1910397ecc6baae525a05b Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 10:28:42 -0300 Subject: [PATCH 54/74] feat(routes): add /reports/ route in CompetitionRoute --- backend/src/routes/competitions.go | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/routes/competitions.go b/backend/src/routes/competitions.go index 48bf180..5166430 100644 --- a/backend/src/routes/competitions.go +++ b/backend/src/routes/competitions.go @@ -31,5 +31,6 @@ func CompetitionsRoute(eng *gin.Engine) { competitionsGroup.POST("/", controller.Create) competitionsGroup.GET("/", controller.GetCompetition) competitionsGroup.PUT("/", controller.CloseCompetition) + competitionsGroup.GET("/reports/", controller.GetCompetitionReport) } } \ No newline at end of file From 89b10080aaea2ce1ee662a549ee4eb6aa7067e0e Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 14:50:06 -0300 Subject: [PATCH 55/74] chore(package): add github.com/aws/aws-sdk-go-v2 --- backend/go.mod | 1 + backend/go.sum | 2 ++ 2 files changed, 3 insertions(+) diff --git a/backend/go.mod b/backend/go.mod index e7a4afe..497a3c2 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -3,6 +3,7 @@ module github.com/joaooliveira247/backend-test go 1.24.1 require ( + github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect github.com/bytedance/sonic v1.13.2 // indirect github.com/bytedance/sonic/loader v0.2.4 // indirect github.com/cloudwego/base64x v0.1.5 // indirect diff --git a/backend/go.sum b/backend/go.sum index cdc227f..3ceafbd 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -1,3 +1,5 @@ +github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM= +github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= From 20369f7dee7db6767401029d2d2c2f2e8aa74e5d Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 14:50:55 -0300 Subject: [PATCH 56/74] chore(package): add github.com/aws/aws-sdk-go-v2/config --- backend/go.mod | 12 ++++++++++++ backend/go.sum | 24 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/backend/go.mod b/backend/go.mod index 497a3c2..214db26 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -4,6 +4,18 @@ go 1.24.1 require ( github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect + github.com/aws/aws-sdk-go-v2/config v1.29.12 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.65 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.25.2 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 // indirect + github.com/aws/smithy-go v1.22.2 // indirect github.com/bytedance/sonic v1.13.2 // indirect github.com/bytedance/sonic/loader v0.2.4 // indirect github.com/cloudwego/base64x v0.1.5 // indirect diff --git a/backend/go.sum b/backend/go.sum index 3ceafbd..2a316a4 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -1,5 +1,29 @@ github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM= github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= +github.com/aws/aws-sdk-go-v2/config v1.29.12 h1:Y/2a+jLPrPbHpFkpAAYkVEtJmxORlXoo5k2g1fa2sUo= +github.com/aws/aws-sdk-go-v2/config v1.29.12/go.mod h1:xse1YTjmORlb/6fhkWi8qJh3cvZi4JoVNhc+NbJt4kI= +github.com/aws/aws-sdk-go-v2/credentials v1.17.65 h1:q+nV2yYegofO/SUXruT+pn4KxkxmaQ++1B/QedcKBFM= +github.com/aws/aws-sdk-go-v2/credentials v1.17.65/go.mod h1:4zyjAuGOdikpNYiSGpsGz8hLGmUzlY8pc8r9QQ/RXYQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.2 h1:pdgODsAhGo4dvzC3JAG5Ce0PX8kWXrTZGx+jxADD+5E= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.2/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.0 h1:90uX0veLKcdHVfvxhkWUQSCi5VabtwMLFutYiRke4oo= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.0/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 h1:PZV5W8yk4OtH1JAuhV2PXwwO9v5G5Aoj+eMCn4T+1Kc= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.17/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4= +github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= +github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= From b301f52109da0adf7f739f8a78a9be2fb8e03e3b Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 14:51:39 -0300 Subject: [PATCH 57/74] chore(package): add github.com/aws/aws-sdk-go-v2/service/ses --- backend/go.mod | 1 + backend/go.sum | 2 ++ 2 files changed, 3 insertions(+) diff --git a/backend/go.mod b/backend/go.mod index 214db26..befe2b3 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -12,6 +12,7 @@ require ( github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect + github.com/aws/aws-sdk-go-v2/service/ses v1.30.1 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.25.2 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.0 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 // indirect diff --git a/backend/go.sum b/backend/go.sum index 2a316a4..6f79fb6 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -16,6 +16,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY= +github.com/aws/aws-sdk-go-v2/service/ses v1.30.1 h1:mZtHKUiz5lo7ohuAi2DKRTv1NEQEtQW30pvQ6QVV68A= +github.com/aws/aws-sdk-go-v2/service/ses v1.30.1/go.mod h1:eZW5lSNTE1tQfMpl6crr/YVJYgEcnk2JQoodg6E63qM= github.com/aws/aws-sdk-go-v2/service/sso v1.25.2 h1:pdgODsAhGo4dvzC3JAG5Ce0PX8kWXrTZGx+jxADD+5E= github.com/aws/aws-sdk-go-v2/service/sso v1.25.2/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.0 h1:90uX0veLKcdHVfvxhkWUQSCi5VabtwMLFutYiRke4oo= From 9205d1e261d609475cb59b438ec7b2d600e3b048 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 17:45:10 -0300 Subject: [PATCH 58/74] chore(package): remove aws packages --- backend/go.mod | 28 +++++++++------------------- backend/go.sum | 48 ++++++++++++++++++------------------------------ 2 files changed, 27 insertions(+), 49 deletions(-) diff --git a/backend/go.mod b/backend/go.mod index befe2b3..a8a12a0 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -3,32 +3,22 @@ module github.com/joaooliveira247/backend-test go 1.24.1 require ( - github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect - github.com/aws/aws-sdk-go-v2/config v1.29.12 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.65 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect - github.com/aws/aws-sdk-go-v2/service/ses v1.30.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.25.2 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.0 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 // indirect - github.com/aws/smithy-go v1.22.2 // indirect + github.com/gin-gonic/gin v1.10.0 + github.com/google/uuid v1.6.0 + gorm.io/driver/postgres v1.5.11 + gorm.io/gorm v1.25.12 +) + +require ( github.com/bytedance/sonic v1.13.2 // indirect github.com/bytedance/sonic/loader v0.2.4 // indirect github.com/cloudwego/base64x v0.1.5 // indirect - github.com/cloudwego/iasm v0.2.0 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect github.com/gin-contrib/sse v1.0.0 // indirect - github.com/gin-gonic/gin v1.10.0 // 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.25.0 // indirect github.com/goccy/go-json v0.10.5 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgx/v5 v5.7.4 // indirect @@ -37,11 +27,13 @@ require ( github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.10 // indirect + github.com/kr/text v0.2.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect golang.org/x/arch v0.15.0 // indirect @@ -52,6 +44,4 @@ require ( golang.org/x/text v0.23.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - gorm.io/driver/postgres v1.5.11 // indirect - gorm.io/gorm v1.25.12 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index 6f79fb6..89155e1 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -1,31 +1,3 @@ -github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM= -github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= -github.com/aws/aws-sdk-go-v2/config v1.29.12 h1:Y/2a+jLPrPbHpFkpAAYkVEtJmxORlXoo5k2g1fa2sUo= -github.com/aws/aws-sdk-go-v2/config v1.29.12/go.mod h1:xse1YTjmORlb/6fhkWi8qJh3cvZi4JoVNhc+NbJt4kI= -github.com/aws/aws-sdk-go-v2/credentials v1.17.65 h1:q+nV2yYegofO/SUXruT+pn4KxkxmaQ++1B/QedcKBFM= -github.com/aws/aws-sdk-go-v2/credentials v1.17.65/go.mod h1:4zyjAuGOdikpNYiSGpsGz8hLGmUzlY8pc8r9QQ/RXYQ= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY= -github.com/aws/aws-sdk-go-v2/service/ses v1.30.1 h1:mZtHKUiz5lo7ohuAi2DKRTv1NEQEtQW30pvQ6QVV68A= -github.com/aws/aws-sdk-go-v2/service/ses v1.30.1/go.mod h1:eZW5lSNTE1tQfMpl6crr/YVJYgEcnk2JQoodg6E63qM= -github.com/aws/aws-sdk-go-v2/service/sso v1.25.2 h1:pdgODsAhGo4dvzC3JAG5Ce0PX8kWXrTZGx+jxADD+5E= -github.com/aws/aws-sdk-go-v2/service/sso v1.25.2/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.0 h1:90uX0veLKcdHVfvxhkWUQSCi5VabtwMLFutYiRke4oo= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.0/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 h1:PZV5W8yk4OtH1JAuhV2PXwwO9v5G5Aoj+eMCn4T+1Kc= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.17/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4= -github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= -github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= @@ -33,9 +5,10 @@ github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCN github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= -github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +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/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= @@ -43,6 +16,8 @@ github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +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= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= @@ -51,6 +26,8 @@ github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0 github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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= @@ -72,6 +49,10 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= @@ -83,7 +64,10 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +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/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= 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/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -94,6 +78,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= @@ -112,9 +97,13 @@ golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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.v3 v3.0.0-20200313102051-9f266ea9e77c/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= @@ -123,4 +112,3 @@ gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSk gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= From 45692997dda67f824049c7363cc1816be453f54b Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 17:49:24 -0300 Subject: [PATCH 59/74] chore(package): add gopkg.in/gomail.v2 --- backend/go.mod | 2 ++ backend/go.sum | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/backend/go.mod b/backend/go.mod index a8a12a0..743bcde 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -43,5 +43,7 @@ require ( golang.org/x/sys v0.31.0 // indirect golang.org/x/text v0.23.0 // indirect google.golang.org/protobuf v1.36.6 // indirect + gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect + gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index 89155e1..e8ba24e 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -101,9 +101,13 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= +gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= 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= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 2e53676f479f0d0527259d7ab7c4d719ea95cb63 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 18:49:08 -0300 Subject: [PATCH 60/74] feat(services) add SendEmail service --- backend/src/services/email.go | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 backend/src/services/email.go diff --git a/backend/src/services/email.go b/backend/src/services/email.go new file mode 100644 index 0000000..db38fa9 --- /dev/null +++ b/backend/src/services/email.go @@ -0,0 +1,42 @@ +package services + +import ( + "fmt" + "log" + + "github.com/joaooliveira247/backend-test/src/config" + "gopkg.in/gomail.v2" +) + +func SendEmail(to, subject, message string) { + smtpHost := "smtp.gmail.com" + smtpPort := 587 + + msg := gomail.NewMessage() + + headers := map[string]string{ + "From": config.SERVICE_EMAIL, + "To": to, + "Subject": subject, + } + + for header, value := range headers { + msg.SetHeader(header, value) + } + + msg.SetBody( + "text/html", + fmt.Sprintf("

Carbon Offset Competition

%s

", message), + ) + + server := gomail.NewDialer( + smtpHost, + smtpPort, + config.SERVICE_EMAIL, + config.PASSWORD_SERVICE_EMAIL, + ) + + if err := server.DialAndSend(msg); err != nil { + log.Fatalf("Send Email: %v", err) + } +} From 8ee59e955e0de2ff9e8578ecd1089cdeaa9b79f6 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 18:51:43 -0300 Subject: [PATCH 61/74] feat(controllers): add SendEmail in GetCompetition method --- backend/src/controllers/competitions.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/backend/src/controllers/competitions.go b/backend/src/controllers/competitions.go index 6ca5a99..5a4f8e5 100644 --- a/backend/src/controllers/competitions.go +++ b/backend/src/controllers/competitions.go @@ -2,12 +2,14 @@ package controllers import ( "errors" + "fmt" "net/http" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/joaooliveira247/backend-test/src/models" "github.com/joaooliveira247/backend-test/src/repositories" + "github.com/joaooliveira247/backend-test/src/services" "gorm.io/gorm" ) @@ -68,6 +70,14 @@ func (ctrl *CompetitionsController) GetCompetition(ctx *gin.Context) { CompetitionID: compCheck.ID, }, ) + services.SendEmail( + user.Email, + "Carbon Offset Competition", + fmt.Sprintf( + "+1 point using your affiliate code: %s", + code, + ), + ) } } ctx.JSON(http.StatusOK, compCheck) From 585e4ddf2711c7282bc8d0d60fa5942ab55afc9b Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 19:01:29 -0300 Subject: [PATCH 62/74] feat(config): add SERVICE_EMAIL var --- backend/src/config/config.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/config/config.go b/backend/src/config/config.go index b2ccfa8..9c8912b 100644 --- a/backend/src/config/config.go +++ b/backend/src/config/config.go @@ -3,9 +3,11 @@ package config import "os" var ( - DATABASE_URL = "" + DATABASE_URL = "" + SERVICE_EMAIL = "" ) func LoadEnv() { DATABASE_URL = os.Getenv("DATABASE_URL") + SERVICE_EMAIL = os.Getenv("SERVICE_EMAIL") } From 9a05a39d50f357a586d3698dc8692660cdd24aff Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 19:02:11 -0300 Subject: [PATCH 63/74] feat(config): add PASSWORD_SERVICE_EMAIL var --- backend/src/config/config.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/config/config.go b/backend/src/config/config.go index 9c8912b..9176f3b 100644 --- a/backend/src/config/config.go +++ b/backend/src/config/config.go @@ -5,9 +5,11 @@ import "os" var ( DATABASE_URL = "" SERVICE_EMAIL = "" + PASSWORD_SERVICE_EMAIL = "" ) func LoadEnv() { DATABASE_URL = os.Getenv("DATABASE_URL") SERVICE_EMAIL = os.Getenv("SERVICE_EMAIL") + PASSWORD_SERVICE_EMAIL = os.Getenv("PASSWORD_SERVICE_EMAIL") } From 5ffb57b4f8833011a476189ae7ef5bf19d24b4a9 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 19:03:22 -0300 Subject: [PATCH 64/74] chore(docker) add SERVICE_EMAIL and PASSWORD_SERVICE_EMAIL env vars in carbon_offset_api --- docker-compose.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker-compose.yaml b/docker-compose.yaml index b8db3c4..c010ff6 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -7,6 +7,8 @@ services: dockerfile: Dockerfile environment: - DATABASE_URL= host=carbon_offset_db user=user password=passwd dbname=carbon_offset port=5432 sslmode=disable + - SERVICE_EMAIL=${SERVICE_EMAIL} + - PASSWORD_SERVICE_EMAIL=${PASSWORD_SERVICE_EMAIL} networks: - carbon_offset_network ports: From c8b47f6b4c1672be878a7d3c9b3c9c61cbd3eaf9 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 19:31:28 -0300 Subject: [PATCH 65/74] feat(controllers): add SendEmail in CloseCompetition method --- backend/src/controllers/competitions.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/backend/src/controllers/competitions.go b/backend/src/controllers/competitions.go index 5a4f8e5..896def3 100644 --- a/backend/src/controllers/competitions.go +++ b/backend/src/controllers/competitions.go @@ -3,6 +3,7 @@ package controllers import ( "errors" "fmt" + "log" "net/http" "github.com/gin-gonic/gin" @@ -116,6 +117,24 @@ func (ctrl *CompetitionsController) CloseCompetition(ctx *gin.Context) { return } + winners, err := ctrl.CompetitionRepository.GetCompetitionReport(compID) + + if err != nil { + log.Printf("error pick winners: %v", err) + } + + for i, report := range winners { + services.SendEmail( + report.Email, + "Carbon Offset Competition Ended", + fmt.Sprintf( + "Congratulations Carbon Offset Competition: %s ended, your position was %d", + compID, + i + 1, + ), + ) + } + ctx.JSON(http.StatusNoContent, nil) } From 9efc375c4f93ff703aeb7588b5294294a5d678af Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 21:16:33 -0300 Subject: [PATCH 66/74] docs(requirements): add requeriments section --- backend/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 backend/README.md diff --git a/backend/README.md b/backend/README.md new file mode 100644 index 0000000..225dd19 --- /dev/null +++ b/backend/README.md @@ -0,0 +1,10 @@ +# 🏭 Carbon Offset API + +![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/joaooliveira247/backend-test/dev/backend) + +## 💻 Requirements: + +### `Go >= 1.24.1` + +### [`Docker`](https://www.docker.com/) & [`Docker compose`](https://docs.docker.com/compose/) + From 3e3e71f978ec7f3a9051e779c620d19e81bb4715 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 21:17:13 -0300 Subject: [PATCH 67/74] docs(documentation): add documentation section --- backend/README.md | 239 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) diff --git a/backend/README.md b/backend/README.md index 225dd19..fd242a5 100644 --- a/backend/README.md +++ b/backend/README.md @@ -8,3 +8,242 @@ ### [`Docker`](https://www.docker.com/) & [`Docker compose`](https://docs.docker.com/compose/) +## 📜 Documentation: + +`/users/` + +
+POST /users/ + +- **Description**: Creates a new user. + +- **Headers**: + + ```plaintext + Content-Type: application/json + + ``` + +- **Request Body**: + + ```json + { + "name": "john", + "email": "john@gmail.com", + "phone": "+5519912345678" + } + ``` + +- **Success Response (201 Created)**: + + ```json + { + "affiliateCode": "1d47bbe5-c7d3-4580-ad2a-c4b192eeeb47" + } + ``` + +- **Errors**: + + - **400 Bad Request**: Invalid request body. + + - **500 Internal Server Error**: Failed to create the entity. + +- **Example Request with cURL**: + +```curl +curl -X POST localhost:8000/users/ \ +-H "Content-Type: application/json" \ +-d '{ + "name": "john", + "email": "john@gmail.com", + "phone": "+5519912345678" +}' +``` +
+ +### + +`/competitions/` + +
+POST /competitions/ + +- **Description**: Creates a new competition. + +- **Headers**: + + ```plaintext + Content-Type: application/json + + ``` + +- **Request Body**: + + ```json + ``` + +- **Success Response (201 Created)**: + + ```json + { + "id": "06ae5f86-46dd-42d3-8e6d-2abe26f6b07e" + } + ``` + +- **Errors**: + + - **409 Conflict**: competition already activated. + + - **500 Internal Server Error**: error create competition. + +- **Example Request with cURL**: + +```curl +curl -X POST localhost:8000/competitions/ \ +-H "Content-Type: application/json" \ +``` +
+ +
+GET /competitions/ + +- **Description**: Get competition activated. + +- **Headers**: + + ```plaintext + Content-Type: application/json + + ``` + +- **Success Response (200 OK / 204 No Content)**: + + ```json + { + "id": "9fbae8ae-3ba9-4582-a931-04d2e3c6aa93", + "createdAt": 1743096181, + "status": true + } + ``` + +- **Example Request with cURL**: + +```curl +curl -X GET localhost:8000/competitions/ \ +-H "Content-Type: application/json" \ +``` +
+ +
+PUT /competitions/ + +- **Description**: Close Competition. + +- **Headers**: + + ```plaintext + Content-Type: application/json + + ``` + +- **Query Parameters**: + + **ID** (required, UUID): Competiton ID. + +- **Request Body**: + + ```json + ``` + +- **Success Response (204 No Content)**: + + ```json + ``` + +- **Errors**: + + - **400 Bad Request**: invalid id. + + - **404 Not Found**: competition not found. + + - **409 Conflict**: competition already activated. + + - **500 Internal Server Error**: closed competition error. + +- **Example Request with cURL**: + +```curl +curl -X PUT localhost:8000/competitions/?ID=e4b5c0cc-2f47-4b29-9883-84f314600f71\ +-H "Content-Type: application/json" \ +``` +
+ +
+GET /competitions/reports/ + +- **Description**: Get competition reports. + +- **Headers**: + + ```plaintext + Content-Type: application/json + ``` + +- **Query Parameters**: + + **ID** (required, UUID): Competiton ID. + +- **Success Response (200 OK)**: + + ```json + [ + { + "name": "User 6", + "points": 10 + }, + { + "name": "User 5", + "points": 10 + }, + { + "name": "User 13", + "points": 9 + }, + { + "name": "User 8", + "points": 8 + }, + { + "name": "User 9", + "points": 8 + }, + { + "name": "User 7", + "points": 6 + }, + { + "name": "User 2", + "points": 4 + }, + { + "name": "User 11", + "points": 4 + }, + { + "name": "User 15", + "points": 4 + }, + { + "name": "User 1", + "points": 2 + } + ] + ``` + +- **Example Request with cURL**: + +```curl +curl -X GET localhost:8000/competitions/reports/?ID=d3dd9c62-5cc0-4b57-b341-ea1876dadac6 \ +-H "Content-Type: application/json" \ +``` +
\ No newline at end of file From 2e05d4ef19b5cbe6ef7cccb62f0214a7249ed72e Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 21:22:00 -0300 Subject: [PATCH 68/74] docs(packages): add Usage libraries section --- backend/README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/backend/README.md b/backend/README.md index fd242a5..1f31cdb 100644 --- a/backend/README.md +++ b/backend/README.md @@ -246,4 +246,16 @@ curl -X PUT localhost:8000/competitions/?ID=e4b5c0cc-2f47-4b29-9883-84f314600f71 curl -X GET localhost:8000/competitions/reports/?ID=d3dd9c62-5cc0-4b57-b341-ea1876dadac6 \ -H "Content-Type: application/json" \ ``` - \ No newline at end of file + + +## 📦 Usage libraries: + +- [gin](github.com/gin-gonic/gin) + +- [gorm](https://gorm.io/) + +- [gorm/postgres](https://github.com/go-gorm/postgres) + +- [uuid](github.com/google/uuid) + +- [gomail](https://pkg.go.dev/gopkg.in/gomail.v2?utm_source=godoc) \ No newline at end of file From c0d10ff87a1f13d6c8565f6d313af891db7d8355 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Fri, 28 Mar 2025 21:28:35 -0300 Subject: [PATCH 69/74] docs(database): add database diagram --- backend/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/README.md b/backend/README.md index 1f31cdb..44731e6 100644 --- a/backend/README.md +++ b/backend/README.md @@ -248,6 +248,10 @@ curl -X GET localhost:8000/competitions/reports/?ID=d3dd9c62-5cc0-4b57-b341-ea18 ``` +## 🗄️ Database Diagram + +![database_diagram](https://i.imgur.com/CaK8HUN.png) + ## 📦 Usage libraries: - [gin](github.com/gin-gonic/gin) From 1cab5e125d4f657cb50a30e3b7de733808d4e442 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Sat, 29 Mar 2025 08:01:17 -0300 Subject: [PATCH 70/74] chore(package): add golang.org/x/time/rate --- backend/go.mod | 1 + backend/go.sum | 2 ++ 2 files changed, 3 insertions(+) diff --git a/backend/go.mod b/backend/go.mod index 743bcde..0ad035c 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -42,6 +42,7 @@ require ( golang.org/x/sync v0.12.0 // indirect golang.org/x/sys v0.31.0 // indirect golang.org/x/text v0.23.0 // indirect + golang.org/x/time v0.11.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect diff --git a/backend/go.sum b/backend/go.sum index e8ba24e..d638a93 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -97,6 +97,8 @@ golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= From 9bd0f9e285e3876654b9554cbb5783eb63cfd90e Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Sat, 29 Mar 2025 08:43:57 -0300 Subject: [PATCH 71/74] feat(middlewares): add limiters var --- backend/src/middlewares/limit.go | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 backend/src/middlewares/limit.go diff --git a/backend/src/middlewares/limit.go b/backend/src/middlewares/limit.go new file mode 100644 index 0000000..d024f46 --- /dev/null +++ b/backend/src/middlewares/limit.go @@ -0,0 +1,7 @@ +package middlewares + +import ( + "sync" +) + +var limiters = sync.Map{} From be2e98fb8e62eab4352245993a331b6586141cd2 Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Sat, 29 Mar 2025 08:44:55 -0300 Subject: [PATCH 72/74] feat(middlewares): add getLimiter func --- backend/src/middlewares/limit.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/backend/src/middlewares/limit.go b/backend/src/middlewares/limit.go index d024f46..8139db1 100644 --- a/backend/src/middlewares/limit.go +++ b/backend/src/middlewares/limit.go @@ -2,6 +2,19 @@ package middlewares import ( "sync" + + "golang.org/x/time/rate" ) var limiters = sync.Map{} + +func getLimiter(ip string) *rate.Limiter { + limiter, ok := limiters.Load(ip) + + if !ok { + newLimiter := rate.NewLimiter(1, 5) + limiters.Store(ip, newLimiter) + return newLimiter + } + return limiter.(*rate.Limiter) +} From a4cf5dd91b4f51984f8a056e108b5f815ef5d28e Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Sat, 29 Mar 2025 08:45:42 -0300 Subject: [PATCH 73/74] feat(middlewares): add RateLimiter func --- backend/src/middlewares/limit.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/backend/src/middlewares/limit.go b/backend/src/middlewares/limit.go index 8139db1..364e486 100644 --- a/backend/src/middlewares/limit.go +++ b/backend/src/middlewares/limit.go @@ -1,8 +1,10 @@ package middlewares import ( + "net/http" "sync" + "github.com/gin-gonic/gin" "golang.org/x/time/rate" ) @@ -18,3 +20,18 @@ func getLimiter(ip string) *rate.Limiter { } return limiter.(*rate.Limiter) } + +func RateLimiter(ctx *gin.Context) { + ip := ctx.ClientIP() + limiter := getLimiter(ip) + + if !limiter.Allow() { + ctx.JSON( + http.StatusTooManyRequests, + gin.H{"error": "too many requests"}, + ) + ctx.Abort() + return + } + ctx.Next() +} From 224f4c2271b5b7d9481535ae959ccf80169cf68c Mon Sep 17 00:00:00 2001 From: joaooliveira247 Date: Sat, 29 Mar 2025 08:47:43 -0300 Subject: [PATCH 74/74] feat(main): add RateLimiter in gin api --- backend/main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/main.go b/backend/main.go index b94d0cd..35092b5 100644 --- a/backend/main.go +++ b/backend/main.go @@ -6,6 +6,7 @@ import ( "github.com/gin-gonic/gin" "github.com/joaooliveira247/backend-test/src/config" "github.com/joaooliveira247/backend-test/src/db" + "github.com/joaooliveira247/backend-test/src/middlewares" "github.com/joaooliveira247/backend-test/src/routes" ) @@ -27,6 +28,7 @@ func main() { } api := gin.Default() + api.Use(middlewares.RateLimiter) routes.RegistryRoutes(api) if err := api.Run(":8000"); err != nil {