CSI-ES-2324/Projs/PD2/internal/server/server.go
2024-05-31 19:23:51 +01:00

176 lines
4.2 KiB
Go

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")
storeUserCert := new(protocol.StoreUserCert)
if err := c.BindJSON(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"})
return
}
} 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"})
return
}
} 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")
message := new(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()})
return
}
message, err := dataStore.GetMessage(user, num)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
return
}
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())
}
}