diff --git a/config.example.yml b/config.example.yml index 8762bb4..145c9cb 100644 --- a/config.example.yml +++ b/config.example.yml @@ -1,4 +1,9 @@ debug: false +scylladb: + host: 127.0.0.1 + username: user + password: password + keyspace: keyspace rabbitmq: host: "127.0.0.1" username: "guest" diff --git a/go.mod b/go.mod index aba4a3f..11ddf58 100644 --- a/go.mod +++ b/go.mod @@ -5,9 +5,12 @@ go 1.19 require ( github.com/andybalholm/brotli v1.0.4 // indirect github.com/fasthttp/websocket v1.5.0 // indirect + github.com/gocql/gocql v1.3.1 // indirect github.com/gofiber/fiber/v2 v2.40.1 // indirect github.com/gofiber/websocket/v2 v2.1.2 // indirect + github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.3.0 // indirect + github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect github.com/klauspost/compress v1.15.12 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.16 // indirect @@ -15,10 +18,13 @@ require ( github.com/rabbitmq/amqp091-go v1.5.0 // indirect github.com/rivo/uniseg v0.4.3 // indirect github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d // indirect + github.com/scylladb/go-reflectx v1.0.1 // indirect + github.com/scylladb/gocqlx/v2 v2.7.0 // indirect github.com/sirupsen/logrus v1.9.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.43.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect golang.org/x/sys v0.3.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index da60851..e98fb39 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,24 @@ github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= 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/fasthttp/websocket v1.5.0 h1:B4zbe3xXyvIdnqjOZrafVFklCUq5ZLo/TqCt5JA1wLE= github.com/fasthttp/websocket v1.5.0/go.mod h1:n0BlOQvJdPbTuBkZT0O5+jk/sp/1/VCzquR1BehI2F4= +github.com/gocql/gocql v1.3.1 h1:BTwM4rux+ah5G3oH6/MQa+tur/TDd/XAAOXDxBBs7rg= +github.com/gocql/gocql v1.3.1/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8= github.com/gofiber/fiber/v2 v2.40.1 h1:pc7n9VVpGIqNsvg9IPLQhyFEMJL8gCs1kneH5D1pIl4= github.com/gofiber/fiber/v2 v2.40.1/go.mod h1:Gko04sLksnHbzLSRBFWPFdzM9Ws9pRxvvIaohJK1dsk= github.com/gofiber/websocket/v2 v2.1.2 h1:EulKyLB/fJgui5+6c8irwEnYQ9FRsrLZfkrq9OfTDGc= github.com/gofiber/websocket/v2 v2.1.2/go.mod h1:S+sKWo0xeC7Wnz5h4/8f6D/NxsrLFIdWDYB3SyVO9pE= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/klauspost/compress v1.14.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= @@ -34,9 +43,14 @@ github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/savsgio/gotils v0.0.0-20211223103454-d0aaa54c5899/go.mod h1:oejLrk1Y/5zOF+c/aHtXqn3TFlzzbAgPWg8zBiAHDas= github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d h1:Q+gqLBOPkFGHyCJxXMRqtUgUbTjI8/Ze8vu8GGyNFwo= github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4= +github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ= +github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= +github.com/scylladb/gocqlx/v2 v2.7.0 h1:/w1VeJHCEAsg9eTculTvIS9eIe/VmEu0clhlH1CF7lc= +github.com/scylladb/gocqlx/v2 v2.7.0/go.mod h1:jKhM0/LkEAhEOSwd10TCMQdlC5x8aEzK7cXjQcPyMJ0= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 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= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -94,6 +108,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index f103b03..c6d5c26 100644 --- a/main.go +++ b/main.go @@ -6,6 +6,8 @@ import ( "clickandjoin.app/websocketserver/modules/config" "clickandjoin.app/websocketserver/modules/rabbitmq" + "clickandjoin.app/websocketserver/modules/scylladb" + "clickandjoin.app/websocketserver/modules/structs" "clickandjoin.app/websocketserver/socketserver" "github.com/gofiber/fiber/v2" @@ -22,26 +24,49 @@ func init() { logrus.Println("Debug:", config.Cfg.Debug) + scylladb.InitDatabase() + go rabbitmq.Init() } func main() { app := fiber.New() + // wait so that rabbitmq can connect + // TODO: better way to handle this + time.Sleep(500 * time.Millisecond) + app.Use("/", func(c *fiber.Ctx) error { // IsWebSocketUpgrade returns true if the client // requested upgrade to the WebSocket protocol. if websocket.IsWebSocketUpgrade(c) { + wsSession := c.Query("auth") + + // no auth query available + if len(wsSession) == 0 { + return c.SendStatus(fiber.StatusUnauthorized) + } + + // validate ws session + + foundWsSession := structs.UserWebSocketSession{Id: wsSession} + + q := scylladb.Session.Query(scylladb.WebSocketSessions.Get("id")).BindStruct(foundWsSession) + + if err := q.GetRelease(&foundWsSession); err != nil { + logrus.Errorln("Failed to get ws session, err:", err) + return c.SendStatus(fiber.StatusInternalServerError) + } + + // TODO: Further security checks such as the change of IP, user agents or whether the session ID has already opened another connection. + c.Locals("allowed", true) return c.Next() } + return fiber.ErrUpgradeRequired }) - // wait so that rabbitmq can connect - // TODO: better way to handle this - time.Sleep(500 * time.Millisecond) - go socketserver.RunHub() socketserver.WebSocketServer(app) diff --git a/modules/config/config.go b/modules/config/config.go index acc6981..a263879 100644 --- a/modules/config/config.go +++ b/modules/config/config.go @@ -11,9 +11,17 @@ var Cfg Config type Config struct { Debug bool + ScyllaDB ScyllaDB `yaml:"scylladb"` RabbitMq RabbitMq } +type ScyllaDB struct { + Host string + Username string + Password string + Keyspace string +} + type RabbitMq struct { Host string Username string diff --git a/modules/scylladb/models.go b/modules/scylladb/models.go new file mode 100644 index 0000000..c3dd2c1 --- /dev/null +++ b/modules/scylladb/models.go @@ -0,0 +1,19 @@ +package scylladb + +import ( + "github.com/scylladb/gocqlx/v2/table" +) + +var ( + WebSocketSessions = table.New(table.Metadata{ + Name: "ws_sessions", + Columns: []string{ + "id", + "user_id", + "user_agent", + "ip", + "last_used", + "created_at"}, + PartKey: []string{"id"}, + }) +) diff --git a/modules/scylladb/scylladb.go b/modules/scylladb/scylladb.go new file mode 100644 index 0000000..fec43d8 --- /dev/null +++ b/modules/scylladb/scylladb.go @@ -0,0 +1,32 @@ +package scylladb + +import ( + "clickandjoin.app/websocketserver/modules/config" + "github.com/gocql/gocql" + "github.com/scylladb/gocqlx/v2" + "github.com/sirupsen/logrus" +) + +var Session gocqlx.Session +var Cluster *gocql.ClusterConfig + +func InitDatabase() { + Cluster = gocql.NewCluster(config.Cfg.ScyllaDB.Host) + + Cluster.Authenticator = gocql.PasswordAuthenticator{ + Username: config.Cfg.ScyllaDB.Username, + Password: config.Cfg.ScyllaDB.Password, + } + + Cluster.Keyspace = config.Cfg.ScyllaDB.Keyspace + + var err error + + Session, err = gocqlx.WrapSession(Cluster.CreateSession()) + + if err != nil { + logrus.Fatal(err) + } + + logrus.Info("Database connected") +} diff --git a/modules/structs/user.go b/modules/structs/user.go new file mode 100644 index 0000000..43c2ddc --- /dev/null +++ b/modules/structs/user.go @@ -0,0 +1,11 @@ +package structs + +// TABLE ws_sessions +type UserWebSocketSession struct { + Id string + UserId string + UserAgent string + Ip string + LastUsed int64 + CreatedAt int64 +}