package server import ( "PD2/internal/protocol" "PD2/internal/utils/cryptoUtils" "crypto/x509" "log" "net/http" "strconv" "github.com/gin-gonic/gin" ) func HandleGetUserCert(c *gin.Context, dataStore DataStore) { user := c.Param("user") userCertPacket, err := dataStore.GetUserCertificate(user) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) } else { c.JSON(http.StatusOK, userCertPacket) } } func HandleStoreUserCert(c *gin.Context, dataStore DataStore) { user := c.Param("user") var storeUserCert protocol.StoreUserCert if err := c.Bind(storeUserCert); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } userCert, err := x509.ParseCertificate(storeUserCert.Certificate) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "User certificate is invalid"}) return } err = dataStore.storeUserCertIfNotExists(user, *userCert) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "User already has a certificate stored in the database"}) return } c.JSON(http.StatusOK, gin.H{}) } func HandleGetUnreadMsgsInfo(c *gin.Context, dataStore DataStore) { user := c.Param("user") pageStr := c.Query("page") pagesizeStr := c.Query("pagesize") var page int var err error if pageStr != "" { page, err = strconv.Atoi(pageStr) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Page is not a number"}) } } else { page = 1 } var pagesize int if pagesizeStr != "" { pagesize, err = strconv.Atoi(pagesizeStr) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Pagesize is not a number"}) } } else { pagesize = 5 } if page <= 0 || pagesize <= 0 { c.JSON(http.StatusBadRequest, gin.H{"error": "Page and Pagesize need to be >= 1"}) return } unreadMsgsInfo, err := dataStore.GetUnreadMsgsInfo(user, page, pagesize) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, unreadMsgsInfo) } func HandleSendMessage(c *gin.Context, dataStore DataStore) { sender := c.Param("user") var message protocol.SendMsg if err := c.BindJSON(message); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if message.ToUID == sender { c.JSON(http.StatusBadRequest, gin.H{"error": "Message sender and receiver cannot be the same user"}) return } if !dataStore.userExists(message.ToUID) { c.JSON(http.StatusBadRequest, gin.H{"error": "Message receiver does not exist"}) return } err := dataStore.AddMessageToQueue(sender, message) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, nil) } func HandleGetMessage(c *gin.Context, dataStore DataStore) { user := c.Param("user") numStr := c.Param("num") num, err := strconv.Atoi(numStr) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) } message, reportError := dataStore.GetMessage(user, num) if reportError != nil { c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) } dataStore.MarkMessageInQueueAsRead(user, num) c.JSON(http.StatusOK, message) } func Run() { //Open connection to DB dataStore, err := OpenDB() if err != nil { log.Fatalln(err) } defer dataStore.db.Close() //Read server keystore keystorePassphrase := readStdin("Insert keystore passphrase") serverKeyStore, err := cryptoUtils.LoadKeyStore("certs/server/server.p12", keystorePassphrase) if err != nil { log.Fatalln(err) } r := gin.Default() r.GET("/message/:user/:num", func(c *gin.Context) { HandleGetMessage(c, dataStore) }) r.GET("/queue/:user", func(c *gin.Context) { HandleGetUnreadMsgsInfo(c, dataStore) }) r.GET("/cert/:user", func(c *gin.Context) { HandleGetUserCert(c, dataStore) }) r.POST("/message/:user", func(c *gin.Context) { HandleSendMessage(c, dataStore) }) r.POST("/cert/:user", func(c *gin.Context) { HandleStoreUserCert(c, dataStore) }) server := http.Server{ Addr: "0.0.0.0:8080", Handler: r, //TODO: Verify if it's the gateway TLSConfig: serverKeyStore.GetServerTLSConfig(), } err = server.ListenAndServeTLS("", "") if err != nil { log.Fatal(err.Error()) } }