From 473510afdff7a513804072f7e3a52422d54f4352 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 21:12:16 +0000 Subject: [PATCH 1/2] feat: Initial conversion of Rails backend to Go This commit contains the initial conversion of the Ruby on Rails backend to a Go application. It includes the basic structure of the Go application, including models, controllers, and a main entry point. The application is located in the `go-backend/` subdirectory and uses the `gonertia` package for Inertia.js integration. --- go-backend/controllers/controllers.go | 36 +++ go-backend/controllers/home_controller.go | 44 +++ .../controllers/home_controller_test.go | 32 +++ go-backend/go.mod | 53 ++++ go-backend/go.sum | 101 +++++++ go-backend/main.go | 44 +++ go-backend/models/models.go | 272 ++++++++++++++++++ package-lock.json | 26 -- vendor/.keep | 0 9 files changed, 582 insertions(+), 26 deletions(-) create mode 100644 go-backend/controllers/controllers.go create mode 100644 go-backend/controllers/home_controller.go create mode 100644 go-backend/controllers/home_controller_test.go create mode 100644 go-backend/go.mod create mode 100644 go-backend/go.sum create mode 100644 go-backend/main.go create mode 100644 go-backend/models/models.go delete mode 100644 vendor/.keep diff --git a/go-backend/controllers/controllers.go b/go-backend/controllers/controllers.go new file mode 100644 index 00000000..92453fbe --- /dev/null +++ b/go-backend/controllers/controllers.go @@ -0,0 +1,36 @@ +package controllers + +import "github.com/romsar/gonertia/v2" + +// ApplicationController handles shared logic for all controllers. +type ApplicationController struct { + Inertia *gonertia.Inertia +} + +// NewApplicationController creates a new ApplicationController. +func NewApplicationController(inertia *gonertia.Inertia) *ApplicationController { + return &ApplicationController{Inertia: inertia} +} + +// UsersController handles requests for users. +type UsersController struct { + Inertia *gonertia.Inertia +} + +// NewUsersController creates a new UsersController. +func NewUsersController(inertia *gonertia.Inertia) *UsersController { + return &UsersController{Inertia: inertia} +} + +// LegislatorsController handles requests for legislators. +type LegislatorsController struct { + Inertia *gonertia.Inertia +} + +// NewLegislatorsController creates a new LegislatorsController. +func NewLegislatorsController(inertia *gonertia.Inertia) *LegislatorsController { + return &LegislatorsController{Inertia: inertia} +} + +// Placeholder for other controllers +// ... diff --git a/go-backend/controllers/home_controller.go b/go-backend/controllers/home_controller.go new file mode 100644 index 00000000..0e15a2ef --- /dev/null +++ b/go-backend/controllers/home_controller.go @@ -0,0 +1,44 @@ +package controllers + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/romsar/gonertia/v2" + "sway-go/models" +) + +// HomeController handles requests for the home page. +type HomeController struct { + Inertia *gonertia.Inertia +} + +// NewHomeController creates a new HomeController. +func NewHomeController(inertia *gonertia.Inertia) *HomeController { + return &HomeController{Inertia: inertia} +} + +// Index renders the home page. +func (hc *HomeController) Index(c *gin.Context) { + // For now, we will assume the user is not logged in. + // Later, we will add logic to check for the current user. + // user, _ := c.Get("user") + + // For the purpose of this translation, we will assume user is nil + var user *models.User + + if user != nil { + if user.IsRegistrationComplete { + c.Redirect(http.StatusFound, "/legislators") + return + } + c.Redirect(http.StatusFound, "/sway_registration") + return + } + + hc.Inertia.Render(c.Writer, c.Request, "Pages/Home", gonertia.Props{ + "name": "Sway", + "isBubbles": true, + "params": c.Request.URL.Query(), + }) +} diff --git a/go-backend/controllers/home_controller_test.go b/go-backend/controllers/home_controller_test.go new file mode 100644 index 00000000..ad8e407d --- /dev/null +++ b/go-backend/controllers/home_controller_test.go @@ -0,0 +1,32 @@ +package controllers + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/gin-gonic/gin" + "github.com/romsar/gonertia/v2" + "github.com/stretchr/testify/assert" +) + +func TestHomeController_Index(t *testing.T) { + // Set up the router + r := gin.Default() + + // Set up gonertia + inertia, err := gonertia.New("{{ .inertia }}") + assert.NoError(t, err) + + homeController := NewHomeController(inertia) + r.GET("/", homeController.Index) + + // Create a request to the index endpoint + req, _ := http.NewRequest("GET", "/", nil) + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + + // Check the response + assert.Equal(t, http.StatusOK, w.Code) + assert.Contains(t, w.Body.String(), "Pages/Home") +} diff --git a/go-backend/go.mod b/go-backend/go.mod new file mode 100644 index 00000000..53b5da62 --- /dev/null +++ b/go-backend/go.mod @@ -0,0 +1,53 @@ +module sway-go + +go 1.23.0 + +toolchain go1.24.3 + +require ( + github.com/gin-gonic/gin v1.11.0 + github.com/romsar/gonertia/v2 v2.0.6 + github.com/stretchr/testify v1.11.1 + gorm.io/driver/sqlite v1.6.0 + gorm.io/gorm v1.30.0 +) + +require ( + github.com/bytedance/sonic v1.14.0 // indirect + github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gin-contrib/sse v1.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.27.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/goccy/go-yaml v1.18.0 // 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.3.0 // 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-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/quic-go v0.54.0 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.3.0 // indirect + go.uber.org/mock v0.5.0 // indirect + golang.org/x/arch v0.20.0 // indirect + golang.org/x/crypto v0.40.0 // indirect + golang.org/x/mod v0.25.0 // indirect + golang.org/x/net v0.42.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.27.0 // indirect + golang.org/x/tools v0.34.0 // indirect + google.golang.org/protobuf v1.36.9 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go-backend/go.sum b/go-backend/go.sum new file mode 100644 index 00000000..98235de3 --- /dev/null +++ b/go-backend/go.sum @@ -0,0 +1,101 @@ +github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= +github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA= +github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= +github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= +github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= +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= +github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= +github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= +github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= +github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= +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.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4= +github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +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/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.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +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/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/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.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +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/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= +github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= +github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg= +github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY= +github.com/romsar/gonertia/v2 v2.0.6 h1:27IKiAA2+BMujLDHtnCcMwAVWqcXwV+LjQmDhBIZf68= +github.com/romsar/gonertia/v2 v2.0.6/go.mod h1:8DOQfQz9D1GHd5M6BtXsaF+CIovjXOx/tVna2LcazvA= +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/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +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.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +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.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA= +github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= +go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= +golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c= +golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= +golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= +golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= +golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= +golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= +golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= +google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= +google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +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/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.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ= +gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8= +gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs= +gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= diff --git a/go-backend/main.go b/go-backend/main.go new file mode 100644 index 00000000..3964b62e --- /dev/null +++ b/go-backend/main.go @@ -0,0 +1,44 @@ +package main + +import ( + "log" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/romsar/gonertia/v2" + "sway-go/controllers" + "sway-go/models" + "gorm.io/driver/sqlite" + "gorm.io/gorm" +) + +func main() { + // Set up Gin + r := gin.Default() + + // Set up gonertia + inertia, err := gonertia.New("{{ .inertia }}") + if err != nil { + log.Fatal(err) + } + + // Set up database + db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{}) + if err != nil { + log.Fatal("failed to connect database") + } + + // Migrate the schema + db.AutoMigrate(&models.User{}, &models.Address{}, &models.APIKey{}, &models.Bill{}, &models.BillCosponsor{}, &models.BillNotification{}, &models.BillScore{}, &models.BillScoreDistrict{}, &models.BillSponsor{}, &models.District{}, &models.Invite{}, &models.Legislator{}, &models.LegislatorDistrictScore{}, &models.LegislatorVote{}, &models.Organization{}, &models.OrganizationBillPosition{}, &models.OrganizationBillPositionChange{}, &models.Passkey{}, &models.PushNotificationSubscription{}, &models.RefreshToken{}, &models.SwayLocale{}, &models.UserAddress{}, &models.UserDistrict{}, &models.UserInviter{}, &models.UserLegislator{}, &models.UserLegislatorEmail{}, &models.UserLegislatorScore{}, &models.UserOrganizationMembership{}, &models.UserOrganizationMembershipInvite{}, &models.UserVote{}, &models.Vote{}) + + // Set up controllers + homeController := controllers.NewHomeController(inertia) + + // Set up routes + r.GET("/", homeController.Index) + + // Start the server + if err := http.ListenAndServe(":8080", r); err != nil { + log.Fatal(err) + } +} diff --git a/go-backend/models/models.go b/go-backend/models/models.go new file mode 100644 index 00000000..9151f734 --- /dev/null +++ b/go-backend/models/models.go @@ -0,0 +1,272 @@ +package models + +import ( + "time" + + "gorm.io/gorm" +) + +// Bill model +type Bill struct { + gorm.Model + Title string + Description string + Session string + BillNumber string + Status string +} + +// BillCosponsor model +type BillCosponsor struct { + gorm.Model + BillID uint + LegislatorID uint +} + +// BillNotification model +type BillNotification struct { + gorm.Model + UserID uint + BillID uint + SentAt time.Time +} + +// BillScore model +type BillScore struct { + gorm.Model + BillID uint + Score int +} + +// BillScoreDistrict model +type BillScoreDistrict struct { + gorm.Model + BillScoreID uint + DistrictID uint +} + +// BillSponsor model +type BillSponsor struct { + gorm.Model + BillID uint + LegislatorID uint +} + +// District model +type District struct { + gorm.Model + Name string + State string + Chamber string + Number string + SwayLocaleID uint +} + +// Invite model +type Invite struct { + gorm.Model + Email string + Token string + InviterID uint + InviteeID uint + AcceptedAt time.Time + OrganizationID uint +} + +// Legislator model +type Legislator struct { + gorm.Model + FullName string + Party string + DistrictID uint +} + +// LegislatorDistrictScore model +type LegislatorDistrictScore struct { + gorm.Model + LegislatorID uint + DistrictID uint + Score int +} + +// LegislatorVote model +type LegislatorVote struct { + gorm.Model + LegislatorID uint + VoteID uint + Vote string +} + +// Organization model +type Organization struct { + gorm.Model + Name string +} + +// OrganizationBillPosition model +type OrganizationBillPosition struct { + gorm.Model + OrganizationID uint + BillID uint + Position string +} + +// OrganizationBillPositionChange model +type OrganizationBillPositionChange struct { + gorm.Model + OrganizationBillPositionID uint + OldPosition string + NewPosition string + ChangedAt time.Time +} + +// Passkey model +type Passkey struct { + gorm.Model + UserID uint + PublicKey string + CredentialID string +} + +// PushNotificationSubscription model +type PushNotificationSubscription struct { + gorm.Model + UserID uint + Endpoint string + P256dh string + Auth string +} + +// RefreshToken model +type RefreshToken struct { + gorm.Model + UserID uint + Token string +} + +// SwayLocale model +type SwayLocale struct { + gorm.Model + Name string +} + +// UserAddress model +type UserAddress struct { + gorm.Model + UserID uint + AddressID uint +} + +// UserDistrict model +type UserDistrict struct { + gorm.Model + UserID uint + DistrictID uint +} + +// UserInviter model +type UserInviter struct { + gorm.Model + UserID uint + InviterID uint +} + +// UserLegislator model +type UserLegislator struct { + gorm.Model + UserID uint + LegislatorID uint +} + +// UserLegislatorEmail model +type UserLegislatorEmail struct { + gorm.Model + UserID uint + LegislatorID uint + Email string + SentAt time.Time +} + +// UserLegislatorScore model +type UserLegislatorScore struct { + gorm.Model + UserID uint + LegislatorID uint + Score int +} + +// UserOrganizationMembership model +type UserOrganizationMembership struct { + gorm.Model + UserID uint + OrganizationID uint + Role string +} + +// UserOrganizationMembershipInvite model +type UserOrganizationMembershipInvite struct { + gorm.Model + UserID uint + OrganizationID uint + InviterID uint + AcceptedAt time.Time +} + +// UserVote model +type UserVote struct { + gorm.Model + UserID uint + VoteID uint + Vote string +} + +// Vote model +type Vote struct { + gorm.Model + BillID uint + Date time.Time + Chamber string + Motion string +} + +// User model +type User struct { + gorm.Model + CurrentSignInAt time.Time + CurrentSignInIP string + Email *string `gorm:"unique"` + FullName string + IsAdmin bool `gorm:"default:false"` + IsEmailVerified bool + IsPhoneVerified bool + IsRegisteredToVote bool + IsRegistrationComplete bool + LastSignInAt time.Time + LastSignInIP string + Phone string `gorm:"unique"` + SignInCount int `gorm:"default:0;not null"` + WebauthnID string `gorm:"unique"` +} + +// Address model +type Address struct { + gorm.Model + AddressableID uint + AddressableType string + City string + Country string + Line1 string + Line2 string + PostalCode string + State string +} + +// APIKey model +type APIKey struct { + gorm.Model + BearerType string `gorm:"not null"` + LastUsedOnUTC time.Time + Name string + TokenDigest string `gorm:"not null;unique"` + BearerID uint `gorm:"not null"` +} diff --git a/package-lock.json b/package-lock.json index 1125418b..b4f83559 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45,7 +45,6 @@ }, "devDependencies": { "@eslint/js": "^9.35.0", - "@prettier/plugin-ruby": "^4.0.4", "@types/eslint__js": "^9.14.0", "@types/lodash": "^4.17.20", "@types/node": "^20.12.13", @@ -2011,16 +2010,6 @@ "url": "https://opencollective.com/popperjs" } }, - "node_modules/@prettier/plugin-ruby": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@prettier/plugin-ruby/-/plugin-ruby-4.0.4.tgz", - "integrity": "sha512-lCpvfS/dQU5WrwN3AQ5vR8qrvj2h5gE41X08NNzAAXvHdM4zwwGRcP2sHSxfu6n6No+ljWCVx95NvJPFTTjCTg==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "prettier": "^3.0.0" - } - }, "node_modules/@react-aria/ssr": { "version": "3.9.10", "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.10.tgz", @@ -11707,21 +11696,6 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "license": "ISC" }, - "node_modules/yaml": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", - "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - } - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/vendor/.keep b/vendor/.keep deleted file mode 100644 index e69de29b..00000000 From 326581c2971d6b6e1ced13c8b996b9b92d6c2bfc Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 15 Oct 2025 01:52:19 +0000 Subject: [PATCH 2/2] feat: Implement UsersController and enhance Go backend structure This commit implements the business logic for the UsersController#Create action, including database interaction and error handling. It also addresses feedback from previous code reviews by: - Refactoring the Go models into a consistent "one model per file" structure. - Removing the committed test.db file and adding it to .gitignore. - Fixing a bug in the UsersController error handling. - Reverting out-of-scope changes to frontend files. --- go-backend/.gitignore | 2 + go-backend/controllers/controllers.go | 56 +++- .../controllers/users_controller_test.go | 49 ++++ go-backend/go.mod | 6 +- go-backend/go.sum | 4 +- go-backend/main.go | 2 + go-backend/models/address.go | 16 ++ go-backend/models/api_key.go | 17 ++ go-backend/models/bill.go | 13 + go-backend/models/bill_cosponsor.go | 10 + go-backend/models/bill_notification.go | 15 + go-backend/models/bill_score.go | 10 + go-backend/models/bill_score_district.go | 10 + go-backend/models/bill_sponsor.go | 10 + go-backend/models/district.go | 13 + go-backend/models/invite.go | 18 ++ go-backend/models/legislator.go | 11 + .../models/legislator_district_score.go | 11 + go-backend/models/legislator_vote.go | 11 + go-backend/models/models.go | 272 ------------------ go-backend/models/organization.go | 9 + .../models/organization_bill_position.go | 11 + .../organization_bill_position_change.go | 16 ++ go-backend/models/passkey.go | 11 + .../models/push_notification_subscription.go | 12 + go-backend/models/refresh_token.go | 10 + go-backend/models/sway_locale.go | 9 + go-backend/models/user.go | 26 ++ go-backend/models/user_address.go | 10 + go-backend/models/user_district.go | 10 + go-backend/models/user_inviter.go | 10 + go-backend/models/user_legislator.go | 10 + go-backend/models/user_legislator_email.go | 16 ++ go-backend/models/user_legislator_score.go | 11 + .../models/user_organization_membership.go | 11 + .../user_organization_membership_invite.go | 16 ++ go-backend/models/user_vote.go | 11 + go-backend/models/vote.go | 16 ++ package-lock.json | 26 ++ 39 files changed, 522 insertions(+), 285 deletions(-) create mode 100644 go-backend/.gitignore create mode 100644 go-backend/controllers/users_controller_test.go create mode 100644 go-backend/models/address.go create mode 100644 go-backend/models/api_key.go create mode 100644 go-backend/models/bill.go create mode 100644 go-backend/models/bill_cosponsor.go create mode 100644 go-backend/models/bill_notification.go create mode 100644 go-backend/models/bill_score.go create mode 100644 go-backend/models/bill_score_district.go create mode 100644 go-backend/models/bill_sponsor.go create mode 100644 go-backend/models/district.go create mode 100644 go-backend/models/invite.go create mode 100644 go-backend/models/legislator.go create mode 100644 go-backend/models/legislator_district_score.go create mode 100644 go-backend/models/legislator_vote.go delete mode 100644 go-backend/models/models.go create mode 100644 go-backend/models/organization.go create mode 100644 go-backend/models/organization_bill_position.go create mode 100644 go-backend/models/organization_bill_position_change.go create mode 100644 go-backend/models/passkey.go create mode 100644 go-backend/models/push_notification_subscription.go create mode 100644 go-backend/models/refresh_token.go create mode 100644 go-backend/models/sway_locale.go create mode 100644 go-backend/models/user.go create mode 100644 go-backend/models/user_address.go create mode 100644 go-backend/models/user_district.go create mode 100644 go-backend/models/user_inviter.go create mode 100644 go-backend/models/user_legislator.go create mode 100644 go-backend/models/user_legislator_email.go create mode 100644 go-backend/models/user_legislator_score.go create mode 100644 go-backend/models/user_organization_membership.go create mode 100644 go-backend/models/user_organization_membership_invite.go create mode 100644 go-backend/models/user_vote.go create mode 100644 go-backend/models/vote.go diff --git a/go-backend/.gitignore b/go-backend/.gitignore new file mode 100644 index 00000000..3767a81c --- /dev/null +++ b/go-backend/.gitignore @@ -0,0 +1,2 @@ +test.db +vendor/ diff --git a/go-backend/controllers/controllers.go b/go-backend/controllers/controllers.go index 92453fbe..a810eb3f 100644 --- a/go-backend/controllers/controllers.go +++ b/go-backend/controllers/controllers.go @@ -1,35 +1,77 @@ package controllers -import "github.com/romsar/gonertia/v2" +import ( + "net/http" + "strconv" + + "github.com/gin-gonic/gin" + "github.com/romsar/gonertia/v2" + "gorm.io/gorm" + "sway-go/models" +) // ApplicationController handles shared logic for all controllers. type ApplicationController struct { Inertia *gonertia.Inertia + DB *gorm.DB } // NewApplicationController creates a new ApplicationController. -func NewApplicationController(inertia *gonertia.Inertia) *ApplicationController { - return &ApplicationController{Inertia: inertia} +func NewApplicationController(inertia *gonertia.Inertia, db *gorm.DB) *ApplicationController { + return &ApplicationController{Inertia: inertia, DB: db} } // UsersController handles requests for users. type UsersController struct { Inertia *gonertia.Inertia + DB *gorm.DB } // NewUsersController creates a new UsersController. -func NewUsersController(inertia *gonertia.Inertia) *UsersController { - return &UsersController{Inertia: inertia} +func NewUsersController(inertia *gonertia.Inertia, db *gorm.DB) *UsersController { + return &UsersController{Inertia: inertia, DB: db} } +// Create handles the creation of user details. +func (uc *UsersController) Create(c *gin.Context) { + // For now, we will assume a placeholder for the current user. + // Later, we will add logic to get the current user. + currentUser := &models.User{} + if err := uc.DB.First(currentUser, 1).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get user."}) + return + } + + var json struct { + BillID int `json:"bill_id"` + FullName string `json:"full_name"` + } + + if err := c.ShouldBindJSON(&json); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + redirectPath := "/bills/" + strconv.Itoa(json.BillID) + + if err := uc.DB.Model(¤tUser).Update("full_name", json.FullName).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save your name. Please try again."}) + return + } + + c.Redirect(http.StatusFound, redirectPath) +} + + // LegislatorsController handles requests for legislators. type LegislatorsController struct { Inertia *gonertia.Inertia + DB *gorm.DB } // NewLegislatorsController creates a new LegislatorsController. -func NewLegislatorsController(inertia *gonertia.Inertia) *LegislatorsController { - return &LegislatorsController{Inertia: inertia} +func NewLegislatorsController(inertia *gonertia.Inertia, db *gorm.DB) *LegislatorsController { + return &LegislatorsController{Inertia: inertia, DB: db} } // Placeholder for other controllers diff --git a/go-backend/controllers/users_controller_test.go b/go-backend/controllers/users_controller_test.go new file mode 100644 index 00000000..005b4636 --- /dev/null +++ b/go-backend/controllers/users_controller_test.go @@ -0,0 +1,49 @@ +package controllers + +import ( + "bytes" + "net/http" + "net/http/httptest" + "testing" + + "github.com/gin-gonic/gin" + "github.com/romsar/gonertia/v2" + "github.com/stretchr/testify/assert" + "gorm.io/driver/sqlite" + "gorm.io/gorm" + "sway-go/models" +) + +func TestUsersController_Create(t *testing.T) { + // Set up the router + r := gin.Default() + + // Set up gonertia + inertia, err := gonertia.New("{{ .inertia }}") + assert.NoError(t, err) + + // Set up database + db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{}) + assert.NoError(t, err) + + // Migrate the schema + db.AutoMigrate(&models.User{}) + + // Create a user + user := models.User{FullName: "Test User"} + db.Create(&user) + + usersController := NewUsersController(inertia, db) + r.POST("/users", usersController.Create) + + // Create a request to the create endpoint + jsonStr := []byte(`{"bill_id":1,"full_name":"John Doe"}`) + req, _ := http.NewRequest("POST", "/users", bytes.NewBuffer(jsonStr)) + req.Header.Set("Content-Type", "application/json") + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + + // Check the response + assert.Equal(t, http.StatusFound, w.Code) + assert.Equal(t, "/bills/1", w.Header().Get("Location")) +} diff --git a/go-backend/go.mod b/go-backend/go.mod index 53b5da62..5ba1dd91 100644 --- a/go-backend/go.mod +++ b/go-backend/go.mod @@ -1,15 +1,13 @@ module sway-go -go 1.23.0 - -toolchain go1.24.3 +go 1.24.3 require ( github.com/gin-gonic/gin v1.11.0 github.com/romsar/gonertia/v2 v2.0.6 github.com/stretchr/testify v1.11.1 gorm.io/driver/sqlite v1.6.0 - gorm.io/gorm v1.30.0 + gorm.io/gorm v1.31.0 ) require ( diff --git a/go-backend/go.sum b/go-backend/go.sum index 98235de3..c7f4fa77 100644 --- a/go-backend/go.sum +++ b/go-backend/go.sum @@ -97,5 +97,5 @@ 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.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ= gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8= -gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs= -gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= +gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY= +gorm.io/gorm v1.31.0/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= diff --git a/go-backend/main.go b/go-backend/main.go index 3964b62e..74661231 100644 --- a/go-backend/main.go +++ b/go-backend/main.go @@ -33,9 +33,11 @@ func main() { // Set up controllers homeController := controllers.NewHomeController(inertia) + usersController := controllers.NewUsersController(inertia, db) // Set up routes r.GET("/", homeController.Index) + r.POST("/users", usersController.Create) // Start the server if err := http.ListenAndServe(":8080", r); err != nil { diff --git a/go-backend/models/address.go b/go-backend/models/address.go new file mode 100644 index 00000000..a21b4b45 --- /dev/null +++ b/go-backend/models/address.go @@ -0,0 +1,16 @@ +package models + +import "gorm.io/gorm" + +// Address model +type Address struct { + gorm.Model + AddressableID uint + AddressableType string + City string + Country string + Line1 string + Line2 string + PostalCode string + State string +} diff --git a/go-backend/models/api_key.go b/go-backend/models/api_key.go new file mode 100644 index 00000000..9a9cd718 --- /dev/null +++ b/go-backend/models/api_key.go @@ -0,0 +1,17 @@ +package models + +import ( + "time" + + "gorm.io/gorm" +) + +// APIKey model +type APIKey struct { + gorm.Model + BearerType string `gorm:"not null"` + LastUsedOnUTC time.Time + Name string + TokenDigest string `gorm:"not null;unique"` + BearerID uint `gorm:"not null"` +} diff --git a/go-backend/models/bill.go b/go-backend/models/bill.go new file mode 100644 index 00000000..08482d2c --- /dev/null +++ b/go-backend/models/bill.go @@ -0,0 +1,13 @@ +package models + +import "gorm.io/gorm" + +// Bill model +type Bill struct { + gorm.Model + Title string + Description string + Session string + BillNumber string + Status string +} diff --git a/go-backend/models/bill_cosponsor.go b/go-backend/models/bill_cosponsor.go new file mode 100644 index 00000000..dd83b355 --- /dev/null +++ b/go-backend/models/bill_cosponsor.go @@ -0,0 +1,10 @@ +package models + +import "gorm.io/gorm" + +// BillCosponsor model +type BillCosponsor struct { + gorm.Model + BillID uint + LegislatorID uint +} diff --git a/go-backend/models/bill_notification.go b/go-backend/models/bill_notification.go new file mode 100644 index 00000000..157917d3 --- /dev/null +++ b/go-backend/models/bill_notification.go @@ -0,0 +1,15 @@ +package models + +import ( + "time" + + "gorm.io/gorm" +) + +// BillNotification model +type BillNotification struct { + gorm.Model + UserID uint + BillID uint + SentAt time.Time +} diff --git a/go-backend/models/bill_score.go b/go-backend/models/bill_score.go new file mode 100644 index 00000000..b540ef5a --- /dev/null +++ b/go-backend/models/bill_score.go @@ -0,0 +1,10 @@ +package models + +import "gorm.io/gorm" + +// BillScore model +type BillScore struct { + gorm.Model + BillID uint + Score int +} diff --git a/go-backend/models/bill_score_district.go b/go-backend/models/bill_score_district.go new file mode 100644 index 00000000..be2dca34 --- /dev/null +++ b/go-backend/models/bill_score_district.go @@ -0,0 +1,10 @@ +package models + +import "gorm.io/gorm" + +// BillScoreDistrict model +type BillScoreDistrict struct { + gorm.Model + BillScoreID uint + DistrictID uint +} diff --git a/go-backend/models/bill_sponsor.go b/go-backend/models/bill_sponsor.go new file mode 100644 index 00000000..a97afaaf --- /dev/null +++ b/go-backend/models/bill_sponsor.go @@ -0,0 +1,10 @@ +package models + +import "gorm.io/gorm" + +// BillSponsor model +type BillSponsor struct { + gorm.Model + BillID uint + LegislatorID uint +} diff --git a/go-backend/models/district.go b/go-backend/models/district.go new file mode 100644 index 00000000..0f036822 --- /dev/null +++ b/go-backend/models/district.go @@ -0,0 +1,13 @@ +package models + +import "gorm.io/gorm" + +// District model +type District struct { + gorm.Model + Name string + State string + Chamber string + Number string + SwayLocaleID uint +} diff --git a/go-backend/models/invite.go b/go-backend/models/invite.go new file mode 100644 index 00000000..6413e729 --- /dev/null +++ b/go-backend/models/invite.go @@ -0,0 +1,18 @@ +package models + +import ( + "time" + + "gorm.io/gorm" +) + +// Invite model +type Invite struct { + gorm.Model + Email string + Token string + InviterID uint + InviteeID uint + AcceptedAt time.Time + OrganizationID uint +} diff --git a/go-backend/models/legislator.go b/go-backend/models/legislator.go new file mode 100644 index 00000000..bf0676da --- /dev/null +++ b/go-backend/models/legislator.go @@ -0,0 +1,11 @@ +package models + +import "gorm.io/gorm" + +// Legislator model +type Legislator struct { + gorm.Model + FullName string + Party string + DistrictID uint +} diff --git a/go-backend/models/legislator_district_score.go b/go-backend/models/legislator_district_score.go new file mode 100644 index 00000000..74ccbbc5 --- /dev/null +++ b/go-backend/models/legislator_district_score.go @@ -0,0 +1,11 @@ +package models + +import "gorm.io/gorm" + +// LegislatorDistrictScore model +type LegislatorDistrictScore struct { + gorm.Model + LegislatorID uint + DistrictID uint + Score int +} diff --git a/go-backend/models/legislator_vote.go b/go-backend/models/legislator_vote.go new file mode 100644 index 00000000..51d17cd3 --- /dev/null +++ b/go-backend/models/legislator_vote.go @@ -0,0 +1,11 @@ +package models + +import "gorm.io/gorm" + +// LegislatorVote model +type LegislatorVote struct { + gorm.Model + LegislatorID uint + VoteID uint + Vote string +} diff --git a/go-backend/models/models.go b/go-backend/models/models.go deleted file mode 100644 index 9151f734..00000000 --- a/go-backend/models/models.go +++ /dev/null @@ -1,272 +0,0 @@ -package models - -import ( - "time" - - "gorm.io/gorm" -) - -// Bill model -type Bill struct { - gorm.Model - Title string - Description string - Session string - BillNumber string - Status string -} - -// BillCosponsor model -type BillCosponsor struct { - gorm.Model - BillID uint - LegislatorID uint -} - -// BillNotification model -type BillNotification struct { - gorm.Model - UserID uint - BillID uint - SentAt time.Time -} - -// BillScore model -type BillScore struct { - gorm.Model - BillID uint - Score int -} - -// BillScoreDistrict model -type BillScoreDistrict struct { - gorm.Model - BillScoreID uint - DistrictID uint -} - -// BillSponsor model -type BillSponsor struct { - gorm.Model - BillID uint - LegislatorID uint -} - -// District model -type District struct { - gorm.Model - Name string - State string - Chamber string - Number string - SwayLocaleID uint -} - -// Invite model -type Invite struct { - gorm.Model - Email string - Token string - InviterID uint - InviteeID uint - AcceptedAt time.Time - OrganizationID uint -} - -// Legislator model -type Legislator struct { - gorm.Model - FullName string - Party string - DistrictID uint -} - -// LegislatorDistrictScore model -type LegislatorDistrictScore struct { - gorm.Model - LegislatorID uint - DistrictID uint - Score int -} - -// LegislatorVote model -type LegislatorVote struct { - gorm.Model - LegislatorID uint - VoteID uint - Vote string -} - -// Organization model -type Organization struct { - gorm.Model - Name string -} - -// OrganizationBillPosition model -type OrganizationBillPosition struct { - gorm.Model - OrganizationID uint - BillID uint - Position string -} - -// OrganizationBillPositionChange model -type OrganizationBillPositionChange struct { - gorm.Model - OrganizationBillPositionID uint - OldPosition string - NewPosition string - ChangedAt time.Time -} - -// Passkey model -type Passkey struct { - gorm.Model - UserID uint - PublicKey string - CredentialID string -} - -// PushNotificationSubscription model -type PushNotificationSubscription struct { - gorm.Model - UserID uint - Endpoint string - P256dh string - Auth string -} - -// RefreshToken model -type RefreshToken struct { - gorm.Model - UserID uint - Token string -} - -// SwayLocale model -type SwayLocale struct { - gorm.Model - Name string -} - -// UserAddress model -type UserAddress struct { - gorm.Model - UserID uint - AddressID uint -} - -// UserDistrict model -type UserDistrict struct { - gorm.Model - UserID uint - DistrictID uint -} - -// UserInviter model -type UserInviter struct { - gorm.Model - UserID uint - InviterID uint -} - -// UserLegislator model -type UserLegislator struct { - gorm.Model - UserID uint - LegislatorID uint -} - -// UserLegislatorEmail model -type UserLegislatorEmail struct { - gorm.Model - UserID uint - LegislatorID uint - Email string - SentAt time.Time -} - -// UserLegislatorScore model -type UserLegislatorScore struct { - gorm.Model - UserID uint - LegislatorID uint - Score int -} - -// UserOrganizationMembership model -type UserOrganizationMembership struct { - gorm.Model - UserID uint - OrganizationID uint - Role string -} - -// UserOrganizationMembershipInvite model -type UserOrganizationMembershipInvite struct { - gorm.Model - UserID uint - OrganizationID uint - InviterID uint - AcceptedAt time.Time -} - -// UserVote model -type UserVote struct { - gorm.Model - UserID uint - VoteID uint - Vote string -} - -// Vote model -type Vote struct { - gorm.Model - BillID uint - Date time.Time - Chamber string - Motion string -} - -// User model -type User struct { - gorm.Model - CurrentSignInAt time.Time - CurrentSignInIP string - Email *string `gorm:"unique"` - FullName string - IsAdmin bool `gorm:"default:false"` - IsEmailVerified bool - IsPhoneVerified bool - IsRegisteredToVote bool - IsRegistrationComplete bool - LastSignInAt time.Time - LastSignInIP string - Phone string `gorm:"unique"` - SignInCount int `gorm:"default:0;not null"` - WebauthnID string `gorm:"unique"` -} - -// Address model -type Address struct { - gorm.Model - AddressableID uint - AddressableType string - City string - Country string - Line1 string - Line2 string - PostalCode string - State string -} - -// APIKey model -type APIKey struct { - gorm.Model - BearerType string `gorm:"not null"` - LastUsedOnUTC time.Time - Name string - TokenDigest string `gorm:"not null;unique"` - BearerID uint `gorm:"not null"` -} diff --git a/go-backend/models/organization.go b/go-backend/models/organization.go new file mode 100644 index 00000000..4502b9cb --- /dev/null +++ b/go-backend/models/organization.go @@ -0,0 +1,9 @@ +package models + +import "gorm.io/gorm" + +// Organization model +type Organization struct { + gorm.Model + Name string +} diff --git a/go-backend/models/organization_bill_position.go b/go-backend/models/organization_bill_position.go new file mode 100644 index 00000000..d71121e4 --- /dev/null +++ b/go-backend/models/organization_bill_position.go @@ -0,0 +1,11 @@ +package models + +import "gorm.io/gorm" + +// OrganizationBillPosition model +type OrganizationBillPosition struct { + gorm.Model + OrganizationID uint + BillID uint + Position string +} diff --git a/go-backend/models/organization_bill_position_change.go b/go-backend/models/organization_bill_position_change.go new file mode 100644 index 00000000..3ea9edc6 --- /dev/null +++ b/go-backend/models/organization_bill_position_change.go @@ -0,0 +1,16 @@ +package models + +import ( + "time" + + "gorm.io/gorm" +) + +// OrganizationBillPositionChange model +type OrganizationBillPositionChange struct { + gorm.Model + OrganizationBillPositionID uint + OldPosition string + NewPosition string + ChangedAt time.Time +} diff --git a/go-backend/models/passkey.go b/go-backend/models/passkey.go new file mode 100644 index 00000000..01e297ea --- /dev/null +++ b/go-backend/models/passkey.go @@ -0,0 +1,11 @@ +package models + +import "gorm.io/gorm" + +// Passkey model +type Passkey struct { + gorm.Model + UserID uint + PublicKey string + CredentialID string +} diff --git a/go-backend/models/push_notification_subscription.go b/go-backend/models/push_notification_subscription.go new file mode 100644 index 00000000..190bd388 --- /dev/null +++ b/go-backend/models/push_notification_subscription.go @@ -0,0 +1,12 @@ +package models + +import "gorm.io/gorm" + +// PushNotificationSubscription model +type PushNotificationSubscription struct { + gorm.Model + UserID uint + Endpoint string + P256dh string + Auth string +} diff --git a/go-backend/models/refresh_token.go b/go-backend/models/refresh_token.go new file mode 100644 index 00000000..47927798 --- /dev/null +++ b/go-backend/models/refresh_token.go @@ -0,0 +1,10 @@ +package models + +import "gorm.io/gorm" + +// RefreshToken model +type RefreshToken struct { + gorm.Model + UserID uint + Token string +} diff --git a/go-backend/models/sway_locale.go b/go-backend/models/sway_locale.go new file mode 100644 index 00000000..55c66495 --- /dev/null +++ b/go-backend/models/sway_locale.go @@ -0,0 +1,9 @@ +package models + +import "gorm.io/gorm" + +// SwayLocale model +type SwayLocale struct { + gorm.Model + Name string +} diff --git a/go-backend/models/user.go b/go-backend/models/user.go new file mode 100644 index 00000000..203a8756 --- /dev/null +++ b/go-backend/models/user.go @@ -0,0 +1,26 @@ +package models + +import ( + "time" + + "gorm.io/gorm" +) + +// User model +type User struct { + gorm.Model + CurrentSignInAt time.Time + CurrentSignInIP string + Email *string `gorm:"unique"` + FullName string + IsAdmin bool `gorm:"default:false"` + IsEmailVerified bool + IsPhoneVerified bool + IsRegisteredToVote bool + IsRegistrationComplete bool + LastSignInAt time.Time + LastSignInIP string + Phone string `gorm:"unique"` + SignInCount int `gorm:"default:0;not null"` + WebauthnID string `gorm:"unique"` +} diff --git a/go-backend/models/user_address.go b/go-backend/models/user_address.go new file mode 100644 index 00000000..aa1c4bd2 --- /dev/null +++ b/go-backend/models/user_address.go @@ -0,0 +1,10 @@ +package models + +import "gorm.io/gorm" + +// UserAddress model +type UserAddress struct { + gorm.Model + UserID uint + AddressID uint +} diff --git a/go-backend/models/user_district.go b/go-backend/models/user_district.go new file mode 100644 index 00000000..b7ad0071 --- /dev/null +++ b/go-backend/models/user_district.go @@ -0,0 +1,10 @@ +package models + +import "gorm.io/gorm" + +// UserDistrict model +type UserDistrict struct { + gorm.Model + UserID uint + DistrictID uint +} diff --git a/go-backend/models/user_inviter.go b/go-backend/models/user_inviter.go new file mode 100644 index 00000000..81ff0390 --- /dev/null +++ b/go-backend/models/user_inviter.go @@ -0,0 +1,10 @@ +package models + +import "gorm.io/gorm" + +// UserInviter model +type UserInviter struct { + gorm.Model + UserID uint + InviterID uint +} diff --git a/go-backend/models/user_legislator.go b/go-backend/models/user_legislator.go new file mode 100644 index 00000000..f85f0515 --- /dev/null +++ b/go-backend/models/user_legislator.go @@ -0,0 +1,10 @@ +package models + +import "gorm.io/gorm" + +// UserLegislator model +type UserLegislator struct { + gorm.Model + UserID uint + LegislatorID uint +} diff --git a/go-backend/models/user_legislator_email.go b/go-backend/models/user_legislator_email.go new file mode 100644 index 00000000..07b65b2e --- /dev/null +++ b/go-backend/models/user_legislator_email.go @@ -0,0 +1,16 @@ +package models + +import ( + "time" + + "gorm.io/gorm" +) + +// UserLegislatorEmail model +type UserLegislatorEmail struct { + gorm.Model + UserID uint + LegislatorID uint + Email string + SentAt time.Time +} diff --git a/go-backend/models/user_legislator_score.go b/go-backend/models/user_legislator_score.go new file mode 100644 index 00000000..89df3b01 --- /dev/null +++ b/go-backend/models/user_legislator_score.go @@ -0,0 +1,11 @@ +package models + +import "gorm.io/gorm" + +// UserLegislatorScore model +type UserLegislatorScore struct { + gorm.Model + UserID uint + LegislatorID uint + Score int +} diff --git a/go-backend/models/user_organization_membership.go b/go-backend/models/user_organization_membership.go new file mode 100644 index 00000000..f4ffd1d0 --- /dev/null +++ b/go-backend/models/user_organization_membership.go @@ -0,0 +1,11 @@ +package models + +import "gorm.io/gorm" + +// UserOrganizationMembership model +type UserOrganizationMembership struct { + gorm.Model + UserID uint + OrganizationID uint + Role string +} diff --git a/go-backend/models/user_organization_membership_invite.go b/go-backend/models/user_organization_membership_invite.go new file mode 100644 index 00000000..016bb3d3 --- /dev/null +++ b/go-backend/models/user_organization_membership_invite.go @@ -0,0 +1,16 @@ +package models + +import ( + "time" + + "gorm.io/gorm" +) + +// UserOrganizationMembershipInvite model +type UserOrganizationMembershipInvite struct { + gorm.Model + UserID uint + OrganizationID uint + InviterID uint + AcceptedAt time.Time +} diff --git a/go-backend/models/user_vote.go b/go-backend/models/user_vote.go new file mode 100644 index 00000000..a251d19e --- /dev/null +++ b/go-backend/models/user_vote.go @@ -0,0 +1,11 @@ +package models + +import "gorm.io/gorm" + +// UserVote model +type UserVote struct { + gorm.Model + UserID uint + VoteID uint + Vote string +} diff --git a/go-backend/models/vote.go b/go-backend/models/vote.go new file mode 100644 index 00000000..ea0f5a79 --- /dev/null +++ b/go-backend/models/vote.go @@ -0,0 +1,16 @@ +package models + +import ( + "time" + + "gorm.io/gorm" +) + +// Vote model +type Vote struct { + gorm.Model + BillID uint + Date time.Time + Chamber string + Motion string +} diff --git a/package-lock.json b/package-lock.json index b4f83559..1125418b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45,6 +45,7 @@ }, "devDependencies": { "@eslint/js": "^9.35.0", + "@prettier/plugin-ruby": "^4.0.4", "@types/eslint__js": "^9.14.0", "@types/lodash": "^4.17.20", "@types/node": "^20.12.13", @@ -2010,6 +2011,16 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@prettier/plugin-ruby": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@prettier/plugin-ruby/-/plugin-ruby-4.0.4.tgz", + "integrity": "sha512-lCpvfS/dQU5WrwN3AQ5vR8qrvj2h5gE41X08NNzAAXvHdM4zwwGRcP2sHSxfu6n6No+ljWCVx95NvJPFTTjCTg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "prettier": "^3.0.0" + } + }, "node_modules/@react-aria/ssr": { "version": "3.9.10", "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.10.tgz", @@ -11696,6 +11707,21 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "license": "ISC" }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "dev": true, + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",