package gateway import ( "PD2/internal/protocol" "PD2/internal/utils/cryptoUtils" "crypto/x509" "log" "net/http" "github.com/gin-gonic/gin" ) func HandleGetMessage(c *gin.Context, keyStore cryptoUtils.KeyStore) { uid, exists := c.Get("uid") if !exists { c.JSON(http.StatusBadRequest, gin.H{"error": "User does not exist"}) return } uidString := uid.(string) num := c.Param("num") if num == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "User does not exist"}) return } statusCode, body, err := forwardGetMessage(keyStore.GetGatewayOutgoingTLSConfig(), uidString, num) if err != nil { log.Println(err.Error()) } else { c.Data(statusCode, "application/json", body) } } func HandleGetUnreadMsgsInfo(c *gin.Context, keyStore cryptoUtils.KeyStore) { page := c.Query("page") pagesize := c.Query("pagesize") uid, exists := c.Get("uid") if !exists { c.JSON(http.StatusBadRequest, gin.H{"error": "User does not exist"}) return } uidString := uid.(string) statusCode, body, err := forwardGetUnreadMsgsInfo(keyStore.GetGatewayOutgoingTLSConfig(), uidString, page, pagesize) if err != nil { log.Println(err.Error()) } else { c.Data(statusCode, "application/json", body) } } func HandleGetUserCert(c *gin.Context, keyStore cryptoUtils.KeyStore) { certificateOwnerUID := c.Param("user") if certificateOwnerUID == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "User does not exist"}) return } statusCode, body, err := forwardGetUserCert(keyStore.GetGatewayOutgoingTLSConfig(), certificateOwnerUID) if err != nil { log.Println(err.Error()) } else { c.Data(statusCode, "application/json", body) } } func HandleSendMessage(c *gin.Context, keyStore cryptoUtils.KeyStore) { sendMsg := new(protocol.SendMsg) err := c.BindJSON(sendMsg) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Request body is not a SendMsg"}) return } uid, exists := c.Get("uid") if !exists { c.JSON(http.StatusBadRequest, gin.H{"error": "User does not exist"}) return } uidString := uid.(string) statusCode, body, err := forwardSendMessage(keyStore.GetGatewayOutgoingTLSConfig(), uidString, *sendMsg) if err != nil { log.Println(err.Error()) } else { c.Data(statusCode, "application/json", body) } } func HandleRegister(c *gin.Context, dataStore DataStore, keyStore cryptoUtils.KeyStore) { postRegister := new(protocol.PostRegister) err := c.BindJSON(postRegister) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Request body is not a PostRegister"}) return } userCert, err := x509.ParseCertificate(postRegister.Certificate) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "User certificate is invalid"}) return } err = keyStore.CheckCert(userCert, postRegister.UID, "MSG SERVICE") if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "User certificate is invalid, not trusted, belongs to another user or has incorrect usage field"}) return } hashedPassword, err := HashPassword(postRegister.Password) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not hash password"}) return } err = dataStore.InsertUser(postRegister.UID, hashedPassword) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not insert user into DB"}) return } storeUserCertificate := protocol.NewStoreUserCert(userCert.Raw) statusCode, body, err := forwardStoreUserCert(keyStore.GetGatewayOutgoingTLSConfig(), postRegister.UID, storeUserCertificate) if err != nil { log.Println(err.Error()) } else { c.Data(statusCode, "application/json", body) } } func HandleLogin(c *gin.Context, dataStore DataStore, keyStore cryptoUtils.KeyStore) { postLogin := new(protocol.PostLogin) err := c.BindJSON(postLogin) if err != nil { c.AbortWithStatus(http.StatusBadRequest) } hashedPassword, err := dataStore.GetPassword(postLogin.UID) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user id or password"}) return } err = CheckPassword(hashedPassword, postLogin.Password) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user id or password"}) return } jwToken, err := GenerateJWT(postLogin.UID) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to create token"}) return } //Send token to user c.JSON(http.StatusOK, gin.H{"token": jwToken}) } func AuthMiddleware(c *gin.Context) { token := c.GetHeader("Token") if token == "" { c.JSON(http.StatusUnauthorized, gin.H{"error": "No authentication token provided"}) c.Abort() return } uid, err := ValidateJWT(token) if err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "Token is invalid or has expired"}) c.Abort() return } c.Set("uid", uid) c.Next() } func Run() { dataStore, err := OpenDB() if err != nil { log.Fatalln("Error opening the database") } defer dataStore.db.Close() passphrase := readStdin("Insert keystore passphrase") keyStore, err := cryptoUtils.LoadKeyStore("certs/gateway/gateway.p12", passphrase) if err != nil { log.Fatalln(err.Error()) } router := gin.Default() auth := router.Group("/", func(c *gin.Context) { AuthMiddleware(c) }) auth.GET("/message/:num", func(c *gin.Context) { HandleGetMessage(c, keyStore) }) auth.GET("/queue", func(c *gin.Context) { HandleGetUnreadMsgsInfo(c, keyStore) }) auth.GET("/cert/:user", func(c *gin.Context) { HandleGetUserCert(c, keyStore) }) auth.POST("/message", func(c *gin.Context) { HandleSendMessage(c, keyStore) }) router.POST("/register", func(c *gin.Context) { HandleRegister(c, dataStore, keyStore) }) router.POST("/login", func(c *gin.Context) { HandleLogin(c, dataStore, keyStore) }) server := http.Server{ Addr: "0.0.0.0:9090", Handler: router, TLSConfig: keyStore.GetGatewayIncomingTLSConfig(), } err = server.ListenAndServeTLS("", "") if err != nil { log.Fatal(err.Error()) } }