Skip to content

Commit

Permalink
added websocket support
Browse files Browse the repository at this point in the history
  • Loading branch information
CharlesMuchogo committed Nov 3, 2023
1 parent f9c96a4 commit e203d77
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 79 deletions.
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ go 1.19

require (
github.com/gin-gonic/gin v1.9.0
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
github.com/jinzhu/gorm v1.9.16
github.com/joho/godotenv v1.5.1
github.com/lib/pq v1.10.7
golang.org/x/crypto v0.7.0
)

require (
github.com/NaySoftware/go-fcm v0.0.0-20190516140123-808e978ddcd2 // indirect
github.com/bytedance/sonic v1.8.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
github.com/NaySoftware/go-fcm v0.0.0-20190516140123-808e978ddcd2 h1:0hjpEzUWez7uca/CUBhfidfotTCCI5fsj6Nb+TW5DLg=
github.com/NaySoftware/go-fcm v0.0.0-20190516140123-808e978ddcd2/go.mod h1:3qVrdgWvoMZMoRG+/nusrCNrcP4RYU4MWGv467XjqLI=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
Expand Down Expand Up @@ -36,6 +34,10 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
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/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
Expand Down
25 changes: 19 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ package main

import (
"fmt"
"time"

"github.com/gorilla/mux"
"log"
"main.go/location"
"main.go/user"
"main.go/websocket"
"net/http"

"github.com/gin-gonic/gin"
_ "github.com/lib/pq"
)

func main() {

//gin.SetMode(gin.ReleaseMode)
fmt.Printf("time now is %s \n", time.Now().Format("2006-01-02T15:04:05.999999Z"))
fmt.Printf("time now is %s \n", time.Now())
r := gin.Default()
public := r.Group("/api")
public.POST("/register", user.Signup)
Expand All @@ -25,7 +26,19 @@ func main() {
public.POST("/request_promotion", user.RequestPromotion)
public.GET("/promote_user", user.PromoteUser)

r.Run(":8001")
fmt.Println("Server started on port 8001")
go func() {
if err := r.Run(":8001"); err != nil {
log.Fatal("HTTP server failed to start: ", err)
}
}()

fmt.Println("HTTP server started on port 8001")
router := mux.NewRouter()
router.HandleFunc("/location", websocket.WsEndpoint)

if err := http.ListenAndServe(":9200", router); err != nil {
log.Fatal("WebSocket server failed to start: ", err)
}
fmt.Println("WS server started on port 9200")

}
136 changes: 66 additions & 70 deletions user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ func UpdateProfile(c *gin.Context) {
}
}


func RequestPromotion(c *gin.Context) {
var requestDetails myStructs.LoginData
if err := c.ShouldBindJSON(&requestDetails); err != nil {
Expand Down Expand Up @@ -78,90 +77,87 @@ func PromoteUser(c *gin.Context) {
}

type DB struct {
*gorm.DB
*gorm.DB
}

func InitDB() (*DB, error) {
db, err := gorm.Open("postgres", databasehandler.GoDotEnvVariable("DATABASEURL"))
if err != nil {
return nil, err
}
db.AutoMigrate(&myStructs.User{})
return &DB{db}, nil
db, err := gorm.Open("postgres", databasehandler.GoDotEnvVariable("DATABASEURL"))
if err != nil {
return nil, err
}
db.AutoMigrate(&myStructs.User{})
return &DB{db}, nil
}

func encryptPassword(password string) (string, error) {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return "", err
}
return string(hashedPassword), nil
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return "", err
}
return string(hashedPassword), nil
}
func Signup(c *gin.Context) {
db, err := InitDB()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
defer db.Close()

var user myStructs.User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

// Assign a default profile photo if none was provided
if user.Profile_photo == "" {
user.Profile_photo = "https://www.pngitem.com/pimgs/m/30-307416_profile-icon-png-image-free-download-searchpng-employee.png"
}

hashedPassword, err := encryptPassword(user.Password)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

user.Password = hashedPassword

if err := db.Create(&user).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, gin.H{"user": user, "message":"signup success"})
}
db, err := InitDB()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
defer db.Close()

var user myStructs.User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

func Login(c *gin.Context) {
db, err := InitDB()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
defer db.Close()
// Assign a default profile photo if none was provided
if user.Profile_photo == "" {
user.Profile_photo = "https://www.pngitem.com/pimgs/m/30-307416_profile-icon-png-image-free-download-searchpng-employee.png"
}

var loginUser myStructs.LoginUser
if err := c.ShouldBindJSON(&loginUser); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
hashedPassword, err := encryptPassword(user.Password)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

fmt.Printf("userid is updated successfully %s \n", loginUser)
user.Password = hashedPassword

if err := db.Create(&user).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

var user myStructs.User
if err := db.Where("email = ?", loginUser.Email).First(&user).Error; err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid email or password"})
return
}
fmt.Printf("userid is updated successfully %s \n", user)
c.JSON(http.StatusOK, gin.H{"user": user, "message": "signup success"})
}

func Login(c *gin.Context) {
db, err := InitDB()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
defer db.Close()

if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(loginUser.Password)); err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid email or password"})
return
}
var loginUser myStructs.LoginUser
if err := c.ShouldBindJSON(&loginUser); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

fmt.Printf("userid is updated successfully %s \n", loginUser)

var user myStructs.User
if err := db.Where("email = ?", loginUser.Email).First(&user).Error; err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid email or password"})
return
}
fmt.Printf("userid is updated successfully %v \n", user)

if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(loginUser.Password)); err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid email or password"})
return
}

c.JSON(http.StatusOK,gin.H{"user": user, "message":"login success"})
c.JSON(http.StatusOK, gin.H{"user": user, "message": "login success"})
}
52 changes: 52 additions & 0 deletions websocket/websocket.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package websocket

import (
"fmt"
"github.com/gorilla/websocket"
"net/http"
)

type Location struct {
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
}

var (
wsUpgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}

wsConn *websocket.Conn
)

func WsEndpoint(w http.ResponseWriter, r *http.Request) {
wsUpgrader.CheckOrigin = func(r *http.Request) bool {
return true
}

wsConn, err := wsUpgrader.Upgrade(w, r, nil)

if err != nil {
fmt.Printf("could not upgrade: %s \n", err.Error())
}
defer wsConn.Close()

for {

var location Location
err := wsConn.ReadJSON(&location)

if err != nil {
fmt.Printf("error reading json: %s \n", err.Error())
}

// Echo the received message back to the client
err = wsConn.WriteJSON(location)
if err != nil {
fmt.Printf("error writing json: %s \n", err.Error())
break
}

}
}

0 comments on commit e203d77

Please sign in to comment.