switched to gin-gonic

This commit is contained in:
$(pass /github/name)
2024-07-11 12:28:39 +02:00
parent 20ed629e92
commit de88a603d5
11 changed files with 330 additions and 169 deletions

38
go.mod
View File

@@ -3,17 +3,41 @@ module GoMembership
go 1.22.2 go 1.22.2
require ( require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/gin-gonic/gin v1.10.0
github.com/gorilla/mux v1.8.1 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
github.com/mattn/go-sqlite3 v1.14.22 gorm.io/driver/sqlite v1.5.6
golang.org/x/crypto v0.24.0 gorm.io/gorm v1.25.10
) )
require ( require (
github.com/bytedance/sonic v1.11.9 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.4 // indirect
github.com/gin-contrib/sse v0.1.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.22.0 // indirect
github.com/goccy/go-json v0.10.3 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // 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.8 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // 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.2 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.25.0 // indirect
golang.org/x/net v0.27.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // 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
gorm.io/driver/sqlite v1.5.6 // indirect
gorm.io/gorm v1.25.10 // indirect
) )

95
go.sum
View File

@@ -1,20 +1,103 @@
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/bytedance/sonic v1.11.9 h1:LFHENlIY/SLzDWverzdOvgMztTxcfcF+cqNsz9pK5zg=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/bytedance/sonic v1.11.9/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/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 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.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I=
github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
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=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
github.com/goccy/go-json v0.10.3/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/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= 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/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 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 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.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
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/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= 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.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
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/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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.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.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
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.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= 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/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= 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/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=
gorm.io/driver/sqlite v1.5.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE= gorm.io/driver/sqlite v1.5.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE=
gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4= gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@@ -1,16 +1,14 @@
package controllers package controllers
import ( import (
"encoding/json"
"GoMembership/internal/config" "GoMembership/internal/config"
"GoMembership/internal/models" "GoMembership/internal/models"
"GoMembership/internal/services" "GoMembership/internal/services"
// "github.com/gorilla/mux"
"net/http" "net/http"
// "strconv" // "strconv"
"GoMembership/internal/utils" "github.com/gin-gonic/gin"
"GoMembership/pkg/logger" "GoMembership/pkg/logger"
) )
@@ -26,24 +24,23 @@ func NewMembershipController(service services.MembershipService) *MembershipCont
return &MembershipController{service} return &MembershipController{service}
} }
func (uc *MembershipController) RegisterSubscription(w http.ResponseWriter, r *http.Request) { func (uc *MembershipController) RegisterSubscription(c *gin.Context) {
rh := utils.NewResponseHandler(w)
var regData MembershipData var regData MembershipData
if err := c.ShouldBindJSON(&regData); err != nil {
if err := json.NewDecoder(r.Body).Decode(&regData); err != nil { logger.Error.Printf("Couln't decode subscription data: %v", err)
logger.Error.Printf("Couldn't decode SubscriptionModel: %v", err) c.JSON(http.StatusBadRequest, gin.H{"error": "Couldn't decode subscription data"})
rh.RespondWithError(http.StatusBadRequest, "Couldn't decode Membershipmodel")
return
} }
logger.Info.Printf("Using API key: %v", config.LoadConfig().Auth.APIKEY) logger.Info.Printf("Using API key: %v", config.LoadConfig().Auth.APIKEY)
if regData.APIKey == "" { if regData.APIKey == "" {
logger.Error.Println("API Key is missing") logger.Error.Println("API Key is missing")
rh.RespondWithError(http.StatusBadRequest, "API Key is required") c.JSON(http.StatusBadRequest, "API Key is missing")
return return
} }
if regData.APIKey != config.LoadConfig().Auth.APIKEY { if regData.APIKey != config.LoadConfig().Auth.APIKEY {
logger.Error.Printf("API Key not valid: %v", regData.APIKey) logger.Error.Printf("API Key not valid: %v", regData.APIKey)
rh.RespondWithError(http.StatusExpectationFailed, "API Key not valid") c.JSON(http.StatusExpectationFailed, "API Key is missing")
return return
} }
logger.Info.Printf("registering subscription: %+v", regData) logger.Info.Printf("registering subscription: %+v", regData)
@@ -52,7 +49,7 @@ func (uc *MembershipController) RegisterSubscription(w http.ResponseWriter, r *h
id, err := uc.service.RegisterSubscription(&regData.Model) id, err := uc.service.RegisterSubscription(&regData.Model)
if err != nil { if err != nil {
logger.Error.Printf("Couldn't register Membershipmodel: %v", err) logger.Error.Printf("Couldn't register Membershipmodel: %v", err)
rh.RespondWithError(http.StatusInternalServerError, "Couldn't register Membershipmodel") c.JSON(http.StatusInternalServerError, "Couldn't register Membershipmodel")
return return
} }
regData.Model.ID = id regData.Model.ID = id

View File

@@ -1,15 +1,12 @@
package controllers package controllers
import ( import (
"encoding/json"
"GoMembership/internal/models" "GoMembership/internal/models"
"GoMembership/internal/services" "GoMembership/internal/services"
// "github.com/gorilla/mux" "github.com/gin-gonic/gin"
"net/http" "net/http"
// "strconv"
"GoMembership/internal/utils"
"GoMembership/pkg/logger" "GoMembership/pkg/logger"
) )
@@ -31,15 +28,13 @@ func NewUserController(service services.UserService, emailService *services.Emai
return &UserController{service, *emailService, consentService, bankAccountService, membershipService} return &UserController{service, *emailService, consentService, bankAccountService, membershipService}
} }
func (uc *UserController) RegisterUser(w http.ResponseWriter, r *http.Request) { func (uc *UserController) RegisterUser(c *gin.Context) {
rh := utils.NewResponseHandler(w)
var regData RegistrationData var regData RegistrationData
if err := json.NewDecoder(r.Body).Decode(&regData); err != nil { if err := c.ShouldBindJSON(&regData); err != nil {
// http.Error(w, err.Error(), http.StatusBadRequest)
logger.Error.Printf("Couldn't decode Userdata: %v", err) logger.Error.Printf("Couldn't decode Userdata: %v", err)
rh.RespondWithError(http.StatusBadRequest, "Couldn't decode userdata") c.JSON(http.StatusBadRequest, gin.H{"error": "Couldn't decode userdata"})
return return
} }
logger.Info.Printf("registering user: %v", regData.User) logger.Info.Printf("registering user: %v", regData.User)
@@ -47,9 +42,8 @@ func (uc *UserController) RegisterUser(w http.ResponseWriter, r *http.Request) {
// Register User // Register User
id, token, err := uc.service.RegisterUser(&regData.User) id, token, err := uc.service.RegisterUser(&regData.User)
if err != nil { if err != nil {
// http.Error(w, err.Error(), http.StatusInternalServerError)
logger.Error.Printf("Couldn't register User: %v", err) logger.Error.Printf("Couldn't register User: %v", err)
rh.RespondWithError(http.StatusInternalServerError, "Couldn't register User") c.JSON(http.StatusInternalServerError, gin.H{"error": "Couldn't register User"})
return return
} }
regData.User.ID = id regData.User.ID = id
@@ -58,7 +52,7 @@ func (uc *UserController) RegisterUser(w http.ResponseWriter, r *http.Request) {
_, err = uc.bankAccountService.RegisterBankAccount(&regData.BankAccount) _, err = uc.bankAccountService.RegisterBankAccount(&regData.BankAccount)
if err != nil { if err != nil {
logger.Error.Printf("Couldn't register bank account: %v", err) logger.Error.Printf("Couldn't register bank account: %v", err)
rh.RespondWithError(http.StatusInternalServerError, "Couldn't register User-BankAccount") c.JSON(http.StatusInternalServerError, gin.H{"error": "Couldn't register User-BankAccount"})
return return
} }
@@ -81,7 +75,7 @@ func (uc *UserController) RegisterUser(w http.ResponseWriter, r *http.Request) {
_, err = uc.consentService.RegisterConsent(&consent) _, err = uc.consentService.RegisterConsent(&consent)
if err != nil { if err != nil {
logger.Error.Printf("Couldn't register consent: %v", err) logger.Error.Printf("Couldn't register consent: %v", err)
rh.RespondWithError(http.StatusInternalServerError, "Couldn't register User-consent") c.JSON(http.StatusInternalServerError, gin.H{"error": "Couldn't register User-consent"})
return return
} }
} }
@@ -90,48 +84,53 @@ func (uc *UserController) RegisterUser(w http.ResponseWriter, r *http.Request) {
_, err = uc.membershipService.RegisterMembership(&regData.Membership) _, err = uc.membershipService.RegisterMembership(&regData.Membership)
if err != nil { if err != nil {
logger.Error.Printf("Couldn't register membership: %v", err) logger.Error.Printf("Couldn't register membership: %v", err)
rh.RespondWithError(http.StatusInternalServerError, "Couldn't register User-membership") c.JSON(http.StatusInternalServerError, gin.H{"error": "Couldn't register User-membership"})
return return
} }
// Send notifications // Send notifications
if err := uc.emailService.SendVerificationEmail(&regData.User, &token); err != nil { if err := uc.emailService.SendVerificationEmail(&regData.User, &token); err != nil {
logger.Error.Printf("Failed to send email verification email to user: %v", err) logger.Error.Printf("Failed to send email verification email to user: %v", err)
// rh.RespondWithError(http.StatusServiceUnavailable, "User creation succeeded, but failed to send welcome email to user") // Proceed without returning error since user registration is successful
} }
// Notify admin of new user registration // Notify admin of new user registration
if err := uc.emailService.NotifyAdminOfNewUser(&regData.User); err != nil { if err := uc.emailService.NotifyAdminOfNewUser(&regData.User); err != nil {
logger.Error.Printf("Failed to notify admin of new user registration: %v", err) logger.Error.Printf("Failed to notify admin of new user registration: %v", err)
// rh.RespondWithError(http.StatusServiceUnavailable, "User creation succeeded, but failed to notify admin of new user registration") // Proceed without returning error since user registration is successful
} }
rh.RespondWithJSON(http.StatusCreated, map[string]interface{}{
c.JSON(http.StatusCreated, gin.H{
"status": "success", "status": "success",
"id": regData.User.ID, "id": regData.User.ID,
}) })
} }
func (uc *UserController) VerifyMailHandler(w http.ResponseWriter, r *http.Request) { func (uc *UserController) VerifyMailHandler(c *gin.Context) {
rh := utils.NewResponseHandler(w) token := c.Query("token")
token := r.URL.Query().Get("token")
if token == "" { if token == "" {
logger.Error.Println("Missing token to verify mail") logger.Error.Println("Missing token to verify mail")
rh.RespondWithError(http.StatusNoContent, "Missing token") c.JSON(http.StatusNoContent, gin.H{"error": "Missing token"})
return return
} }
user, err := uc.service.VerifyUser(&token) user, err := uc.service.VerifyUser(&token)
if err != nil { if err != nil {
logger.Error.Printf("Cannot verify user: %v", err) logger.Error.Printf("Cannot verify user: %v", err)
rh.RespondWithError(http.StatusUnauthorized, "Cannot verify user") c.JSON(http.StatusUnauthorized, gin.H{"error": "Cannot verify user"})
return
} }
membership, err := uc.membershipService.FindMembershipByUserID(user.ID) membership, err := uc.membershipService.FindMembershipByUserID(user.ID)
if err != nil { if err != nil {
logger.Error.Printf("Cannot get membership of user %v: %v", user.ID, err) logger.Error.Printf("Cannot get membership of user %v: %v", user.ID, err)
rh.RespondWithError(http.StatusInternalServerError, "Cannot get Membership of user") c.JSON(http.StatusInternalServerError, gin.H{"error": "Cannot get Membership of user"})
return
} }
uc.emailService.SendWelcomeEmail(user, membership) uc.emailService.SendWelcomeEmail(user, membership)
c.Status(http.StatusOK)
} }
/* func (uc *UserController) LoginUser(w http.ResponseWriter, r *http.Request) { /* func (uc *UserController) LoginUser(w http.ResponseWriter, r *http.Request) {

View File

@@ -1,17 +1,33 @@
package middlewares package middlewares
import ( import (
"GoMembership/pkg/logger"
"net/http"
"time" "time"
"GoMembership/pkg/logger"
"github.com/gin-gonic/gin"
) )
// LoggerMiddleware logs each incoming HTTP request // LoggerMiddleware logs the incoming requests.
func LoggerMiddleware(next http.Handler) http.Handler { func LoggerMiddleware() gin.HandlerFunc {
return http.HandlerFunc( return func(c *gin.Context) {
func(w http.ResponseWriter, r *http.Request) { startTime := time.Now()
start := time.Now()
logger.Info.Printf("%s %s %s", r.Method, r.RequestURI, time.Since(start)) // Process the request
next.ServeHTTP(w, r) c.Next()
})
// Calculate the latency
latency := time.Since(startTime)
// Get the status code
statusCode := c.Writer.Status()
// Log the details
logger.Info.Printf("| %3d | %13v | %15s | %-7s %#v\n",
statusCode,
latency,
c.ClientIP(),
c.Request.Method,
c.Request.URL.Path,
)
}
} }

View File

@@ -1,23 +1,27 @@
package repositories package repositories
import ( import (
"GoMembership/internal/constants"
"time" "time"
"GoMembership/internal/constants"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/clause"
"GoMembership/internal/models" "GoMembership/internal/models"
"GoMembership/pkg/errors" "GoMembership/pkg/errors"
"gorm.io/gorm/clause" "GoMembership/pkg/logger"
) )
type UserRepository interface { type UserRepository interface {
CreateUser(user *models.User) (int64, error) CreateUser(user *models.User) (int64, error)
UpdateUser(userID int64, user *models.User) error
FindUserByID(id int64) (*models.User, error) FindUserByID(id int64) (*models.User, error)
FindUserByEmail(email string) (*models.User, error) FindUserByEmail(email string) (*models.User, error)
SetVerificationToken(user *models.User, token *string) (int64, error) SetVerificationToken(user *models.User, token *string) (int64, error)
IsVerified(userID *int64) (bool, error) IsVerified(userID *int64) (bool, error)
VerifyUserOfToken(token *string) (int64, error) VerifyUserOfToken(token *string) (*models.User, error)
} }
type userRepository struct { type userRepository struct {
@@ -36,11 +40,12 @@ func (repo *userRepository) CreateUser(user *models.User) (int64, error) {
return user.ID, nil return user.ID, nil
} }
func (repo *userRepository) UpdateUser(userID int64, updates map[string]interface{}) error { func (repo *userRepository) UpdateUser(userID int64, user *models.User) error {
if len(updates) == 0 { logger.Info.Printf("Updating User: %#v\n", user)
if user == nil {
return errors.ErrNoData return errors.ErrNoData
} }
result := repo.db.Session(&gorm.Session{FullSaveAssociations: true}).Model(&models.User{}).Where("id = ?", userID).Updates(&updates) result := repo.db.Session(&gorm.Session{FullSaveAssociations: true}).Updates(&user)
if result.Error != nil { if result.Error != nil {
return result.Error return result.Error
} }
@@ -54,7 +59,7 @@ func (repo *userRepository) UpdateUser(userID int64, updates map[string]interfac
func (repo *userRepository) FindUserByID(id int64) (*models.User, error) { func (repo *userRepository) FindUserByID(id int64) (*models.User, error) {
var user models.User var user models.User
result := repo.db.First(&user, id) result := repo.db.Preload("Consents").Preload("BankAccount").Preload("Verification").Preload("Membership").First(&user, id)
if result.Error != nil { if result.Error != nil {
if result.Error == gorm.ErrRecordNotFound { if result.Error == gorm.ErrRecordNotFound {
return nil, gorm.ErrRecordNotFound return nil, gorm.ErrRecordNotFound
@@ -88,38 +93,40 @@ func (repo *userRepository) IsVerified(userID *int64) (bool, error) {
return user.Status != constants.UnverifiedStatus, nil return user.Status != constants.UnverifiedStatus, nil
} }
func (repo *userRepository) VerifyUserOfToken(token *string) (int64, error) { func (repo *userRepository) VerifyUserOfToken(token *string) (*models.User, error) {
var emailVerification models.Verification var emailVerification models.Verification
result := repo.db.Where("verification_token = ?", token).First(&emailVerification) result := repo.db.Where("verification_token = ?", token).First(&emailVerification)
if result.Error != nil { if result.Error != nil {
if result.Error == gorm.ErrRecordNotFound { if result.Error == gorm.ErrRecordNotFound {
return 0, gorm.ErrRecordNotFound return nil, gorm.ErrRecordNotFound
} }
return 0, result.Error return nil, result.Error
} }
// Check if the user is already verified // Check if the user is already verified
verified, err := repo.IsVerified(&emailVerification.UserID) verified, err := repo.IsVerified(&emailVerification.UserID)
if err != nil { if err != nil {
return 0, err return nil, err
}
user, err := repo.FindUserByID(emailVerification.UserID)
if err != nil {
return nil, err
} }
if verified { if verified {
return emailVerification.UserID, gorm.ErrRecordNotFound return user, errors.ErrAlreadyVerified
} }
// Update user status to active // Update user status to active
t := time.Now() t := time.Now()
emailVerification.EmailVerifiedAt = &t emailVerification.EmailVerifiedAt = &t
update := map[string]interface{}{ user.Status = constants.VerifiedStatus
"status": constants.VerifiedStatus, user.Verification = emailVerification
"verifications": emailVerification,
} err = repo.UpdateUser(emailVerification.UserID, user)
err = repo.UpdateUser(emailVerification.UserID, update)
if err != nil { if err != nil {
return 0, err return nil, err
} }
return emailVerification.UserID, nil return user, nil
} }
func (repo *userRepository) SetVerificationToken(user *models.User, token *string) (int64, error) { func (repo *userRepository) SetVerificationToken(user *models.User, token *string) (int64, error) {

View File

@@ -2,18 +2,14 @@ package routes
import ( import (
"GoMembership/internal/controllers" "GoMembership/internal/controllers"
// "GoMembership/internal/middlewares"
"GoMembership/pkg/logger"
// "net/http"
"github.com/gorilla/mux" "github.com/gin-gonic/gin"
) )
func RegisterRoutes(router *mux.Router, userController *controllers.UserController, membershipController *controllers.MembershipController) { func RegisterRoutes(router *gin.Engine, userController *controllers.UserController, membershipController *controllers.MembershipController) {
logger.Info.Println("Registering backend/api/register route") router.GET("/backend/verify", userController.VerifyMailHandler)
router.HandleFunc("/backend/api/verify", userController.VerifyMailHandler).Methods("GET") router.POST("/backend/api/register", userController.RegisterUser)
router.HandleFunc("/backend/api/register", userController.RegisterUser).Methods("POST") router.POST("/backend/api/register/subscription", membershipController.RegisterSubscription)
router.HandleFunc("/backend/api/register/subscription", membershipController.RegisterSubscription).Methods("POST")
// router.HandleFunc("/login", userController.LoginUser).Methods("POST") // router.HandleFunc("/login", userController.LoginUser).Methods("POST")
} }

View File

@@ -6,13 +6,13 @@ import (
"GoMembership/internal/config" "GoMembership/internal/config"
"GoMembership/internal/controllers" "GoMembership/internal/controllers"
"GoMembership/internal/database" "GoMembership/internal/database"
"GoMembership/internal/middlewares" // "GoMembership/internal/middlewares"
"GoMembership/internal/repositories" "GoMembership/internal/repositories"
"GoMembership/internal/routes" "GoMembership/internal/routes"
"GoMembership/internal/services" "GoMembership/internal/services"
"GoMembership/pkg/logger" "GoMembership/pkg/logger"
"github.com/gorilla/mux" "github.com/gin-gonic/gin"
) )
func Run() { func Run() {
@@ -35,12 +35,11 @@ func Run() {
userService := services.NewUserService(userRepo) userService := services.NewUserService(userRepo)
userController := controllers.NewUserController(userService, emailService, consentService, bankAccountService, membershipService) userController := controllers.NewUserController(userService, emailService, consentService, bankAccountService, membershipService)
membershipController := controllers.NewMembershipController(membershipService) membershipController := controllers.NewMembershipController(membershipService)
router := mux.NewRouter()
// router.Handle("/csrf-token", middlewares.GenerateCSRFTokenHandler()).Methods("GET")
// Apply CSRF middleware router := gin.Default()
// router.Use(middlewares.CSRFMiddleware) // gin.SetMode(gin.ReleaseMode)
router.Use(middlewares.LoggerMiddleware) router.Use(gin.Logger())
// router.Use(middlewares.LoggerMiddleware())
routes.RegisterRoutes(router, userController, membershipController) routes.RegisterRoutes(router, userController, membershipController)
// create subrouter for teh authenticated area /account // create subrouter for teh authenticated area /account

View File

@@ -39,6 +39,7 @@ func (service *userService) RegisterUser(user *models.User) (int64, string, erro
return -1, err return -1, err
} }
user.Password = string(hashedPassword) */ user.Password = string(hashedPassword) */
// TODO: Validate Data
user.Status = constants.UnverifiedStatus user.Status = constants.UnverifiedStatus
user.CreatedAt = time.Now() user.CreatedAt = time.Now()
user.UpdatedAt = time.Now() user.UpdatedAt = time.Now()
@@ -53,7 +54,7 @@ func (service *userService) RegisterUser(user *models.User) (int64, string, erro
return -1, "", err return -1, "", err
} }
logger.Info.Printf("user: %+v", user) logger.Info.Printf("TOKEN: %v", token)
_, err = service.repo.SetVerificationToken(user, &token) _, err = service.repo.SetVerificationToken(user, &token)
if err != nil { if err != nil {
return -1, "", err return -1, "", err
@@ -62,11 +63,7 @@ func (service *userService) RegisterUser(user *models.User) (int64, string, erro
} }
func (service *userService) VerifyUser(token *string) (*models.User, error) { func (service *userService) VerifyUser(token *string) (*models.User, error) {
userID, err := service.repo.VerifyUserOfToken(token) user, err := service.repo.VerifyUserOfToken(token)
if err != nil {
return nil, err
}
user, err := service.repo.FindUserByID(userID)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,67 +1,110 @@
<!DOCTYPE html> <!doctype html>
<html lang="de"> <html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Willkommen beim Dörpsmobil Hasloh e.V.</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
margin: 0;
padding: 20px;
background-color: #f9f9f9;
}
.container {
max-width: 600px;
margin: 0 auto;
padding: 20px;
background-color: #fff;
border: 1px solid #ddd;
border-radius: 8px;
}
h1 {
color: #007b5e;
}
p {
margin-bottom: 1em;
}
.contact-info {
margin-top: 20px;
}
.contact-info strong {
display: block;
margin-bottom: 5px;
}
a {
color: #007b5e;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
</style>
</head>
<body> <body>
<div class="container"> <div
<h1>{{.Firstname}} {{.LastName}} hat sich registriert</h1> style="
<p>Ein neues Vereinsmitglied hat sich registriert</p> background-color: #f2f5f7;
<p>{{.Firstname}} {{.LastName}} hat sich registriert. Hier sind die Daten:</p> color: #242424;
<br> font-family: &quot;Helvetica Neue&quot;, &quot;Arial Nova&quot;,
<div class="contact-info"> &quot;Nimbus Sans&quot;, Arial, sans-serif;
<strong>Registrierungsdaten:</strong> font-size: 16px;
Name: {{.Firstname}} {{.LastName}} <br> font-weight: 400;
Email: {{.Email}}<br> letter-spacing: 0.15008px;
IBAN: {{.IBAN}}<br> line-height: 1.5;
BIC: {{.BIC}}<br> margin: 0;
Mandatsreferenz: {{.MandateReference}}<br> padding: 32px 0;
min-height: 100%;
width: 100%;
"
>
<table
align="center"
width="100%"
style="margin: 0 auto; max-width: 600px; background-color: #ffffff"
role="presentation"
cellspacing="0"
cellpadding="0"
border="0"
>
<tbody>
<tr style="width: 100%">
<td>
<div style="padding: 0px 24px 0px 24px">
<a
href="https://carsharing-hasloh.de"
style="text-decoration: none"
target="_blank"
><img
alt="Carsharing-Hasloh"
src="https://carsharing-hasloh.de/images/CarsharingSH-Hasloh-LOGO.jpeg"
style="
outline: none;
border: none;
text-decoration: none;
vertical-align: middle;
display: inline-block;
max-width: 100%;
"
/></a>
</div> </div>
<p>Mit freundlichen Grüßen,<br> <div style="font-weight: normal; padding: 0px 24px 16px 24px">
der Server Moin Du Vorstand 👋,
</div>
<div style="font-weight: normal; padding: 0px 24px 16px 24px">
<p>
Ein neues Mitglied!!!<br />{{.FirstName}} {{.LastName}} hat
sich regitriert.
</p> </p>
</div> </div>
<div
style="
font-size: 22px;
font-weight: normal;
text-align: center;
padding: 0px 24px 0px 24px;
"
>
Hier sind die Daten:
</div>
<div style="font-weight: normal; padding: 16px 24px 0px 24px">
<ul>
<li>
<strong>Das gebuchtes Modell</strong>:
<ul>
<li><strong>Name</strong>: {{.Modellname}}</li>
<li><strong>Preis/Monat</strong>: {{.PreisMonat}}</li>
<li><strong>Preis/h</strong>: {{.PreisStunde}}</li>
</ul>
</li>
<li><strong>Name:</strong> {{.FirstName}} {{.LastName}}</li>
<li>
<strong>Adresse:</strong> {{.Address}},{{.ZipCode}}
{{.City}}
</li>
<li><strong>Geburtsdatum:</strong> {{.DateOfBirth}}</li>
<li><strong>Email:</strong> {{.Email}}</li>
<li><strong>Telefon:</strong> {{.Phone}}</li>
<li><strong>IBAN:</strong> {{.IBAN}}</li>
</ul>
</div>
<div style="padding: 16px 0px 16px 0px">
<hr
style="
width: 100%;
border: none;
border-top: 1px solid #cccccc;
margin: 0;
"
/>
</div>
<div style="font-weight: normal; padding: 16px 24px 16px 24px">
<p>Mit freundlichen Grüßen,</p>
<p>Dein untertänigster Wolkenrechner</p>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</body> </body>
</html> </html>