upstream sync

This commit is contained in:
Senad Uka
2023-10-19 07:57:48 +02:00
parent 5b1acd1c5f
commit 44efa194fc
5 changed files with 93 additions and 12 deletions

View File

@@ -248,7 +248,7 @@ func GetContractByID(c *gin.Context) {
} }
// Fetch contract // Fetch contract
contract, st, err := contract.GetContractByID(contractID) contract, st, err := contract.GetContractByID(uint(contractID))
if err != nil { if err != nil {
c.JSON(st, gin.H{"error": err.Error()}) c.JSON(st, gin.H{"error": err.Error()})
return return

View File

@@ -1,17 +1,22 @@
package controllers package controllers
import ( import (
"context"
"encoding/json" "encoding/json"
"errors" "errors"
"log" "log"
"math/big"
"net/http" "net/http"
"strconv" "strconv"
"time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
"gitlab.com/pactual1/backend/config"
"gitlab.com/pactual1/backend/database/contract" "gitlab.com/pactual1/backend/database/contract"
"gitlab.com/pactual1/backend/database/device" "gitlab.com/pactual1/backend/database/device"
"gitlab.com/pactual1/backend/models" "gitlab.com/pactual1/backend/models"
"gitlab.com/pactual1/backend/services/blockchain"
"gitlab.com/pactual1/backend/shared" "gitlab.com/pactual1/backend/shared"
) )
@@ -37,18 +42,18 @@ func SaveDeviceInfo(c *gin.Context) {
if err := shared.GetDb().Unscoped().Where("device_id = ?", deviceInfo.ExternalDeviceID).First(&device).Error; err != nil { if err := shared.GetDb().Unscoped().Where("device_id = ?", deviceInfo.ExternalDeviceID).First(&device).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
// Create new device // Create new device
newDevice := models.Device{ device = models.Device{
IMEI: deviceInfo.IMEI, IMEI: deviceInfo.IMEI,
IMSI: deviceInfo.IMSI, IMSI: deviceInfo.IMSI,
DeviceID: deviceInfo.ExternalDeviceID, DeviceID: deviceInfo.ExternalDeviceID,
DeviceConfiguration: string(rawData), DeviceConfiguration: string(rawData),
} }
if err := shared.GetDb().Create(&newDevice).Error; err != nil { if err := shared.GetDb().Create(&device).Error; err != nil {
log.Printf("CREATE -Device DB Error: %v", err) log.Printf("CREATE -Device DB Error: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not create new device"}) c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not create new device"})
return return
} }
deviceInfo.DeviceID = newDevice.ID deviceInfo.DeviceID = device.ID
} else { } else {
log.Printf("CREATE -Device DB Error: %v", err) log.Printf("CREATE -Device DB Error: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Database error"}) c.JSON(http.StatusInternalServerError, gin.H{"error": "Database error"})
@@ -76,6 +81,33 @@ func SaveDeviceInfo(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not save device info"}) c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not save device info"})
return return
} }
if device.CurrentContractID != nil {
deviceContract, _, err := contract.GetContractByID(*device.CurrentContractID)
if err != nil {
log.Printf("SaveDeviceInfo - GetContractByID error : %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not fetch device contract"})
return
}
if deviceContract.Status == models.ContractStatusActive {
deviceInfoBytes, _ := json.Marshal(deviceInfo)
deviceInfoEncryptedStr, err := shared.NewEncryptionClient(config.AppConfig.Service.BlockchainSecret).Encrypt(string(deviceInfoBytes))
if err != nil {
log.Printf("SaveDeviceInfo - Enrypt error : %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not encrypt device info"})
return
}
err = blockchain.NewService(config.AppConfig.Blockchain).AddIOTData(context.Background(), shared.CovertUintToByte32(deviceContract.ID), shared.CovertUintToByte32(device.ID), big.NewInt(time.Now().Unix()), []byte(deviceInfoEncryptedStr))
if err != nil {
log.Printf("SaveDeviceInfo CREATE -DeviceInfo Blockchain Error: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not save device info in blockchain"})
return
}
}
}
log.Printf("Successfully received and saved device info: %v", deviceInfo) log.Printf("Successfully received and saved device info: %v", deviceInfo)
c.JSON(http.StatusOK, gin.H{"message": "Successfully received and saved device info", "data": deviceInfo}) c.JSON(http.StatusOK, gin.H{"message": "Successfully received and saved device info", "data": deviceInfo})
} }
@@ -105,8 +137,7 @@ func GetDeviceData(c *gin.Context) {
return return
} }
contract, st, err := contract.GetContractByID(contractID) contract, st, err := contract.GetContractByID(uint(contractID))
if err != nil { if err != nil {
c.JSON(st, gin.H{"error": err.Error()}) c.JSON(st, gin.H{"error": err.Error()})
return return

View File

@@ -1,6 +1,7 @@
package contract package contract
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"log" "log"
@@ -9,8 +10,10 @@ import (
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
"github.com/lib/pq" "github.com/lib/pq"
"gitlab.com/pactual1/backend/config"
"gitlab.com/pactual1/backend/database/device" "gitlab.com/pactual1/backend/database/device"
"gitlab.com/pactual1/backend/models" "gitlab.com/pactual1/backend/models"
"gitlab.com/pactual1/backend/services/blockchain"
"gitlab.com/pactual1/backend/shared" "gitlab.com/pactual1/backend/shared"
) )
@@ -128,6 +131,12 @@ func UpdateContract(contract models.Contract) (models.Contract, int, error) {
} }
} }
// get old contract to compare updates
oldContract, status, err := GetContractByID(contract.ID)
if err != nil {
return contract, status, err
}
err = shared.GetDb().Transaction(func(tx *gorm.DB) error { err = shared.GetDb().Transaction(func(tx *gorm.DB) error {
// Update contract // Update contract
if err := tx.Model(contract).Updates(contract).Error; err != nil { if err := tx.Model(contract).Updates(contract).Error; err != nil {
@@ -151,14 +160,48 @@ func UpdateContract(contract models.Contract) (models.Contract, int, error) {
return contract, http.StatusInternalServerError, err return contract, http.StatusInternalServerError, err
} }
return GetContractByID(uint64(contract.ID)) contract, status, err = GetContractByID(contract.ID)
if err != nil {
return contract, status, err
}
// Create contract in blockchain only when it is signed
if oldContract.Status != contract.Status && contract.Status == models.ContractStatusSigned {
err = blockchain.NewService(config.AppConfig.Blockchain).CreateContract(context.Background(), shared.CovertUintToByte32(contract.ID))
if err != nil {
log.Printf("UpdateContract Error: Could not create contract in blockchain: %v", err)
return contract, http.StatusInternalServerError, err
}
}
if contract.Status == models.ContractStatusSigned {
// Register devices in blockchain if contract is signed
for _, device := range devices {
var found bool
for _, deviceID := range oldContract.DeviceIDs {
if device.ID == uint(deviceID) {
found = true
break
}
}
if !found {
err = blockchain.NewService(config.AppConfig.Blockchain).RegisterNewDeviceID(context.Background(), shared.CovertUintToByte32(contract.ID), shared.CovertUintToByte32(device.ID))
if err != nil {
log.Printf("UpdateContract Error: Could not register contract device in blockchain: %v", err)
return contract, http.StatusInternalServerError, err
}
}
}
}
return contract, status, err
} }
func validateContractDevices(contractID uint, devices []models.Device) (int, error) { func validateContractDevices(contractID uint, devices []models.Device) (int, error) {
for _, device := range devices { for _, device := range devices {
if device.CurrentContractID != nil && *device.CurrentContractID != contractID { if device.CurrentContractID != nil && *device.CurrentContractID != contractID {
currentDeviceContract, status, err := GetContractByID(uint64(*device.CurrentContractID)) currentDeviceContract, status, err := GetContractByID(*device.CurrentContractID)
if err != nil { if err != nil {
return status, err return status, err
} }
@@ -173,7 +216,7 @@ func validateContractDevices(contractID uint, devices []models.Device) (int, err
return http.StatusOK, nil return http.StatusOK, nil
} }
func GetContractByID(contractID uint64) (models.Contract, int, error) { func GetContractByID(contractID uint) (models.Contract, int, error) {
// Fetch the contract creation date based on contractID // Fetch the contract creation date based on contractID
var contract models.Contract var contract models.Contract

View File

@@ -29,7 +29,7 @@ func NewService(blockchainConfig config.Blockchain) Service {
type Service interface { type Service interface {
CreateContract(ctx context.Context, contractID [32]byte) error CreateContract(ctx context.Context, contractID [32]byte) error
AddIOTData(ctx context.Context, contractID [32]byte, deviceID [32]byte, timestamp *big.Int, data []byte) error AddIOTData(ctx context.Context, contractID [32]byte, deviceID [32]byte, timestamp *big.Int, data []byte) error
RegisterNewDeviceIDs(ctx context.Context, contractID [32]byte, deviceIDs [][32]byte) error RegisterNewDeviceID(ctx context.Context, contractID [32]byte, deviceID [32]byte) error
} }
func (s *service) signerFunc(address common.Address, txn *types.Transaction) (*types.Transaction, error) { func (s *service) signerFunc(address common.Address, txn *types.Transaction) (*types.Transaction, error) {
@@ -100,13 +100,13 @@ func (s *service) CreateContract(ctx context.Context, contractID [32]byte) error
} }
// map devices with blockchain contract // map devices with blockchain contract
func (s *service) RegisterNewDeviceIDs(ctx context.Context, contractID [32]byte, deviceIDs [][32]byte) error { func (s *service) RegisterNewDeviceID(ctx context.Context, contractID [32]byte, deviceID [32]byte) error {
conn, contract, err := s.getClient(ctx) conn, contract, err := s.getClient(ctx)
if err != nil { if err != nil {
return err return err
} }
txn, err := contract.RegisterNewDeviceIds(s.getTransactOpts(), contractID, deviceIDs) txn, err := contract.RegisterNewDeviceId(s.getTransactOpts(), contractID, deviceID)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -7,10 +7,17 @@ import (
"crypto/cipher" "crypto/cipher"
"crypto/rand" "crypto/rand"
"encoding/base64" "encoding/base64"
"encoding/binary"
"fmt" "fmt"
"io" "io"
) )
func CovertUintToByte32(id uint) [32]byte {
b := make([]byte, 32)
binary.LittleEndian.PutUint32(b, uint32(id))
return [32]byte(b)
}
type EncryptionClient interface { type EncryptionClient interface {
Encrypt(string) (string, error) Encrypt(string) (string, error)
Decrypt(string) (string, error) Decrypt(string) (string, error)