Upstream sync

This commit is contained in:
Senad Uka
2023-09-18 12:27:40 +02:00
parent 9750aa2c37
commit 1f30f85787
30 changed files with 309 additions and 150 deletions

1
.gitignore vendored
View File

@@ -7,6 +7,7 @@
# Output of the go coverage tool, specifically when used with LiteIDE # Output of the go coverage tool, specifically when used with LiteIDE
*.out *.out
backend
debug debug
.vscode .vscode
.vs/ .vs/

View File

@@ -23,8 +23,9 @@ func Load() error {
Service: Service{ Service: Service{
// 9000 DEFAULT FOR DEV ENVIRONMENT // 9000 DEFAULT FOR DEV ENVIRONMENT
Port: getEnv("NOVATECH_SERVICE_PORT", "9000"), Port: getEnv("NOVATECH_SERVICE_PORT", "9000"),
Environment: getEnv("NOVATECH_SERVICE_ENVIRONMENT", "DEV"), Environment: getEnv("NOVATECH_SERVICE_ENVIRONMENT", "DEV"),
BlockchainSecret: getEnv("NOVATECH_SERVICE_BLOCKCHAIN_SECRET", "novatech_service_blockchain_secret"),
}, },
AdminService: Service{ AdminService: Service{
// 8080 DEFAULT FOR DEV ENVIRONMENT // 8080 DEFAULT FOR DEV ENVIRONMENT
@@ -32,14 +33,12 @@ func Load() error {
Environment: getEnv("NOVATECH_ADMIN_SERVICE_ENVIRONMENT", "DEV"), Environment: getEnv("NOVATECH_ADMIN_SERVICE_ENVIRONMENT", "DEV"),
}, },
Database: Database{ Database: Database{
UserName: getEnv("NOVATECH_DATABASE_USERNAME", "root"), UserName: getEnv("NOVATECH_DATABASE_USERNAME", "root"),
Password: getEnv("NOVATECH_DATABASE_PASSWORD", "root"), Password: getEnv("NOVATECH_DATABASE_PASSWORD", "root"),
DatabaseName: getEnv("NOVATECH_DATABASE_NAME", "postgres"), DatabaseName: getEnv("NOVATECH_DATABASE_NAME", "postgres"),
HostName: getEnv("NOVATECH_DATABASE_ADDRESS", "localhost"), HostName: getEnv("NOVATECH_DATABASE_ADDRESS", "localhost"),
Port: getEnv("NOVATECH_DATABASE_PORT", " "), Port: getEnv("NOVATECH_DATABASE_PORT", " "),
}, },
} }
return nil return nil

View File

@@ -2,25 +2,24 @@ package config
// Config stores application configuration // Config stores application configuration
type Config struct { type Config struct {
Service Service Service Service
AdminService Service AdminService Service
Database Database Database Database
} }
// Service contains configuration for service // Service contains configuration for service
type Service struct { type Service struct {
Port string Port string
Environment string Environment string
WebPageURL string WebPageURL string
BlockchainSecret string
} }
// Database configuration // Database configuration
type Database struct { type Database struct {
UserName string UserName string
Password string Password string
DatabaseName string DatabaseName string
HostName string HostName string
Port string Port string
} }

View File

@@ -13,16 +13,15 @@ import (
type AuthController struct{} type AuthController struct{}
func (AuthController) HandleLogin(c *gin.Context) {
func (AuthController)HandleLogin(c *gin.Context) { userId := "123"
userId:="123" username := "Beast"
username:="Beast" roles := []string{shared.RoleAdmin, shared.RoleProUser}
roles:= []string{shared.RoleAdmin, shared.RoleProUser}
// do user auth here // do user auth here
//issue token //issue token
token, err := middlewares.GenerateToken([]byte(middlewares.SigningKey), userId,username, roles) token, err := middlewares.GenerateToken([]byte(middlewares.SigningKey), userId, username, roles)
if err != nil { if err != nil {
log.Printf("Unable to generate token %v", err) log.Printf("Unable to generate token %v", err)
c.JSON(http.StatusInternalServerError, err) c.JSON(http.StatusInternalServerError, err)

View File

@@ -20,42 +20,40 @@ func SaveDeviceInfofunc(c *gin.Context) {
err := json.Unmarshal(rawData, &deviceInfo) err := json.Unmarshal(rawData, &deviceInfo)
if err != nil { if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON payload"}) c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON payload"})
log.Printf("Invalid json pyload : %v",err) log.Printf("Invalid json pyload : %v", err)
return return
} }
deviceInfo.RawJSON = string(rawData) deviceInfo.RawJSON = string(rawData)
// Attempt to find the device by IMEI; if not found, create a new device // Attempt to find the device by IMEI; if not found, create a new device
var device models.Device var device models.Device
if err := shared.GetDb().Where("imei = ?", deviceInfo.IMEI).First(&device).Error; err != nil { if err := shared.GetDb().Where("imei = ?", deviceInfo.IMEI).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{ newDevice := models.Device{
IMEI: deviceInfo.IMEI, IMEI: deviceInfo.IMEI,
IMSI: deviceInfo.IMSI, IMSI: deviceInfo.IMSI,
DeviceConfiguration: string(rawData), DeviceConfiguration: string(rawData),
} }
if err := shared.GetDb().Create(&newDevice).Error; err != nil { if err := shared.GetDb().Create(&newDevice).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
}
deviceInfo.DeviceID = newDevice.ID
} else {
log.Printf("CREATE -Device DB Error: %v",err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Database error"})
return return
} }
deviceInfo.DeviceID = newDevice.ID
} else { } else {
deviceInfo.DeviceID = device.ID log.Printf("CREATE -Device DB Error: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Database error"})
return
} }
} else {
deviceInfo.DeviceID = device.ID
}
// Save deviceInfo to your database // Save deviceInfo to your database
if err := shared.GetDb().Create(&deviceInfo).Error; err != nil { if err := shared.GetDb().Create(&deviceInfo).Error; err != nil {
log.Printf("SaveDeviceInfo CREATE -DeviceInfo DB Error: %v",err) log.Printf("SaveDeviceInfo CREATE -DeviceInfo DB Error: %v", err)
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
} }

View File

@@ -46,7 +46,6 @@ func TestSaveDeviceInfofunc(t *testing.T) {
t.Fatalf("Expected no error, got %v", err) t.Fatalf("Expected no error, got %v", err)
} }
assert.Equal(t, 400, resp.StatusCode) assert.Equal(t, 400, resp.StatusCode)
}) })
@@ -65,7 +64,7 @@ func TestSaveDeviceInfofunc(t *testing.T) {
t.Run("it should return 200 when all conditions are correct", func(t *testing.T) { t.Run("it should return 200 when all conditions are correct", func(t *testing.T) {
// Add a valid payload // Add a valid payload
deviceInfo := map[string]interface{}{ deviceInfo := map[string]interface{}{
"IMEI": "SOME_VALID_IMEI", "IMEI": "SOME_VALID_IMEI",
"SomeOtherField": "Value", "SomeOtherField": "Value",
} }

View File

@@ -6,10 +6,10 @@ package controllers
import "github.com/gin-gonic/gin" import "github.com/gin-gonic/gin"
func GetSecretText(c *gin.Context){ func GetSecretText(c *gin.Context) {
c.JSON(200, "Hi this is a secret message. Auth was successful!") c.JSON(200, "Hi this is a secret message. Auth was successful!")
} }
func GetPublicText(c *gin.Context){ func GetPublicText(c *gin.Context) {
c.JSON(200, "Hi this is a public message!") c.JSON(200, "Hi this is a public message!")
} }

View File

@@ -7,3 +7,4 @@ NOVATECH_DATABASE_PASSWORD=password
NOVATECH_DATABASE_NAME=dbname NOVATECH_DATABASE_NAME=dbname
NOVATECH_DATABASE_ADDRESS=localhost NOVATECH_DATABASE_ADDRESS=localhost
NOVATECH_DATABASE_PORT=5432 NOVATECH_DATABASE_PORT=5432
NOVATECH_SERVICE_BLOCKCHAIN_SECRET="abc&1*~#^2^#s0^=)^^7%b34"

3
go.mod
View File

@@ -1,6 +1,6 @@
module gitlab.com/pactual1/backend module gitlab.com/pactual1/backend
go 1.21.0 go 1.21
require ( require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go v3.2.0+incompatible
@@ -59,6 +59,7 @@ require (
golang.org/x/net v0.10.0 // indirect golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect golang.org/x/text v0.9.0 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/protobuf v1.30.0 // indirect google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

3
go.sum
View File

@@ -206,8 +206,9 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=

18
main.go
View File

@@ -8,7 +8,7 @@ import (
"gitlab.com/pactual1/backend/config" "gitlab.com/pactual1/backend/config"
"gitlab.com/pactual1/backend/models" "gitlab.com/pactual1/backend/models"
"gitlab.com/pactual1/backend/routes" "gitlab.com/pactual1/backend/routes"
"gitlab.com/pactual1/backend/services/contact" "gitlab.com/pactual1/backend/services/contract"
"gitlab.com/pactual1/backend/services/erp" "gitlab.com/pactual1/backend/services/erp"
"gitlab.com/pactual1/backend/services/messaging" "gitlab.com/pactual1/backend/services/messaging"
"gitlab.com/pactual1/backend/shared" "gitlab.com/pactual1/backend/shared"
@@ -22,7 +22,6 @@ var DB *gorm.DB
func main() { func main() {
// LOAD APPLICATION CONFIGURATION // LOAD APPLICATION CONFIGURATION
err := config.Load() err := config.Load()
if err != nil { if err != nil {
@@ -55,31 +54,34 @@ func main() {
// Start the admin server in a separate goroutine // Start the admin server in a separate goroutine
go func() { go func() {
port := config.AppConfig.Service.Port port := config.AppConfig.Service.Port
fmt.Println("Admin server listening on :" + port) fmt.Println("Admin server listening on :" + port)
http.ListenAndServe(":" + port, mux) http.ListenAndServe(":"+port, mux)
}() }()
// Initialize channels // Initialize channels
messagingChannel := make(chan string) messagingChannel := make(chan string)
erpChannel := make(chan string) erpChannel := make(chan string)
contactChannel := make(chan string) contractChannel := make(chan string)
// Start services and pass the respective channels // Start services and pass the respective channels
go messaging.MessagingService(messagingChannel) go messaging.MessagingService(messagingChannel)
go erp.ERPService(erpChannel) go erp.ERPService(erpChannel)
go contact.ContactService(contactChannel)
encryptionClient := shared.NewEncryptionClient(config.AppConfig.Service.BlockchainSecret)
contractService := contract.NewService(contractChannel, shared.GetDb(), encryptionClient)
go contractService.ContractService()
// Sending messages via channels // Sending messages via channels
messagingChannel <- "Send an email" messagingChannel <- "Send an email"
erpChannel <- "Update ERP record" erpChannel <- "Update ERP record"
contactChannel <- "Update contact info" contractChannel <- "Update contract info"
// Initialize Gin // Initialize Gin
r := gin.Default() r := gin.Default()
routes.InitRouter(r) routes.InitRouter(r)
// Start the Gin server on another port // Start the Gin server on another port
port := config.AppConfig.AdminService.Port port := config.AppConfig.AdminService.Port
fmt.Println("Application server listening on :" + port) fmt.Println("Application server listening on :" + port)
r.Run(":" + port) r.Run(":" + port)

View File

@@ -5,9 +5,9 @@
package middlewares package middlewares
import ( import (
"strings"
"github.com/gin-gonic/gin"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
"strings"
"time" "time"
) )
@@ -83,7 +83,7 @@ func GenerateToken(key []byte, userId string, username string, roles []string) (
claims := make(jwt.MapClaims) claims := make(jwt.MapClaims)
claims["user_id"] = userId claims["user_id"] = userId
claims["username"] = username claims["username"] = username
claims["exp"]=time.Now().Add(time.Hour * 72).UnixNano() / int64(time.Millisecond) claims["exp"] = time.Now().Add(time.Hour*72).UnixNano() / int64(time.Millisecond)
//Set user roles //Set user roles
claims["roles"] = roles claims["roles"] = roles
@@ -102,4 +102,3 @@ func ValidateToken(tokenString string, key string) (*jwt.Token, error) {
return token, err return token, err
} }

View File

@@ -4,7 +4,7 @@ import "github.com/jinzhu/gorm"
type Company struct { type Company struct {
gorm.Model gorm.Model
Name string Name string
Password string Password string
Email string Email string
Avatar string Avatar string
@@ -12,7 +12,6 @@ type Company struct {
Devices []Device Devices []Device
} }
// func FetchCompanies(companies *[]Company) (err error) { // func FetchCompanies(companies *[]Company) (err error) {
// db := gorm.GetDb() // db := gorm.GetDb()
@@ -22,12 +21,12 @@ type Company struct {
// return nil // return nil
// } // }
func (Company)Update() (bool, error) { func (Company) Update() (bool, error) {
return false, nil return false, nil
} }
func (Company)Create() (bool, error) { func (Company) Create() (bool, error) {
return false, nil return false, nil
} }
func (Company)Delete() (bool, error) { func (Company) Delete() (bool, error) {
return false, nil return false, nil
} }

23
models/contract.go Normal file
View File

@@ -0,0 +1,23 @@
package models
import "github.com/jinzhu/gorm"
type Contract struct {
gorm.Model
Name string
DeviceID []uint
BuyerID uint
Status string
BlockchainID string
ContractInfos []ContractInfo
}
func (Contract) Update() (bool, error) {
return false, nil
}
func (Contract) Create() (bool, error) {
return false, nil
}
func (Contract) Delete() (bool, error) {
return false, nil
}

18
models/contract_info.go Normal file
View File

@@ -0,0 +1,18 @@
package models
import "github.com/jinzhu/gorm"
type ContractInfo struct {
gorm.Model
RawJSON string `json:"raw_json" gorm:"type:json"`
}
func (ContractInfo) Update() (bool, error) {
return false, nil
}
func (ContractInfo) Create() (bool, error) {
return false, nil
}
func (ContractInfo) Delete() (bool, error) {
return false, nil
}

View File

@@ -1,8 +1,7 @@
package models package models
type SimpleCRUD interface { type SimpleCRUD interface {
Create() (bool,error) Create() (bool, error)
Update()( bool,error) Update() (bool, error)
Delete() (bool,error) Delete() (bool, error)
} }

View File

@@ -4,20 +4,20 @@ import "github.com/jinzhu/gorm"
type Device struct { type Device struct {
gorm.Model gorm.Model
DeviceName string DeviceName string
IMEI string `json:"imei"` IMEI string `json:"imei"`
IMSI string `json:"imsi"` IMSI string `json:"imsi"`
DeviceConfiguration string `gorm:"type:json"` DeviceConfiguration string `gorm:"type:json"`
CompanyID uint CompanyID uint
DeviceInfos []DeviceInfo DeviceInfos []DeviceInfo
} }
func (Device)Update() (bool, error) { func (Device) Update() (bool, error) {
return false, nil return false, nil
} }
func (Device)Create() (bool, error) { func (Device) Create() (bool, error) {
return false, nil return false, nil
} }
func (Device)Delete() (bool, error) { func (Device) Delete() (bool, error) {
return false, nil return false, nil
} }

View File

@@ -10,30 +10,29 @@ type Location struct {
// ImportantInfo holds fields that are important for quick access. // ImportantInfo holds fields that are important for quick access.
type SensorData struct { type SensorData struct {
IMEI string `json:"imei"` IMEI string `json:"imei"`
IMSI string `json:"imsi"` IMSI string `json:"imsi"`
Timestamp int64 `json:"timestamp"` Timestamp int64 `json:"timestamp"`
Lat float64 `json:"lat"` Lat float64 `json:"lat"`
Lon float64 `json:"lon"` Lon float64 `json:"lon"`
WifiLoc Location `json:"wifi_location"` WifiLoc Location `json:"wifi_location"`
CellLoc Location `json:"cell_location"` CellLoc Location `json:"cell_location"`
Temperature float64 `json:"temperature"` Temperature float64 `json:"temperature"`
} }
type DeviceInfo struct { type DeviceInfo struct {
gorm.Model gorm.Model
RawJSON string `json:"raw_json" gorm:"type:json"` RawJSON string `json:"raw_json" gorm:"type:json"`
SensorData SensorData
DeviceID uint DeviceID uint
} }
func (DeviceInfo)Update() (bool, error) { func (DeviceInfo) Update() (bool, error) {
return false, nil return false, nil
} }
func (DeviceInfo)Create() (bool, error) { func (DeviceInfo) Create() (bool, error) {
return false, nil return false, nil
} }
func (DeviceInfo)Delete() (bool, error) { func (DeviceInfo) Delete() (bool, error) {
return false, nil return false, nil
} }

View File

@@ -4,19 +4,19 @@ import "github.com/jinzhu/gorm"
type User struct { type User struct {
gorm.Model gorm.Model
Username string Username string
Password string Password string
Email string Email string
Avatar string Avatar string
CompanyID uint CompanyID uint
} }
func (User)Update() (bool, error) { func (User) Update() (bool, error) {
return false, nil return false, nil
} }
func (User)Create() (bool, error) { func (User) Create() (bool, error) {
return false, nil return false, nil
} }
func (User)Delete() (bool, error) { func (User) Delete() (bool, error) {
return false, nil return false, nil
} }

View File

@@ -12,12 +12,12 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
func RegisterProtectedRoutes(r *gin.Engine){ func RegisterProtectedRoutes(r *gin.Engine) {
authGroup := r.Group("/auth") authGroup := r.Group("/auth")
authGroup.Use(middlewares.AuthHandler("admin")) authGroup.Use(middlewares.AuthHandler("admin"))
{ {
authGroup.GET("/getmessage",controllers.GetSecretText) authGroup.GET("/getmessage", controllers.GetSecretText)
} }
} }

View File

@@ -6,9 +6,8 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
func RegisterPublicRoutes(r *gin.Engine){ func RegisterPublicRoutes(r *gin.Engine) {
r.GET("/publicmessage", controllers.GetPublicText) r.GET("/publicmessage", controllers.GetPublicText)
r.POST("/device_info", controllers.SaveDeviceInfofunc) r.POST("/device_info", controllers.SaveDeviceInfofunc)
} }

View File

@@ -15,12 +15,12 @@ import (
func InitRouter(engine *gin.Engine) { func InitRouter(engine *gin.Engine) {
InitMiddleware(engine) InitMiddleware(engine)
authController := new(controllers.AuthController) authController := new(controllers.AuthController)
engine.POST("/login", authController.HandleLogin) engine.POST("/login", authController.HandleLogin)
RegisterProtectedRoutes(engine) RegisterProtectedRoutes(engine)
RegisterPublicRoutes(engine) RegisterPublicRoutes(engine)
RegisterUtilityRoutes(engine) RegisterUtilityRoutes(engine)
} }
func InitMiddleware(engine *gin.Engine){ func InitMiddleware(engine *gin.Engine) {
engine.Use(middlewares.CORSMiddleware()); engine.Use(middlewares.CORSMiddleware())
} }

View File

@@ -6,11 +6,11 @@ package routes
import "github.com/gin-gonic/gin" import "github.com/gin-gonic/gin"
func RegisterUtilityRoutes(r *gin.Engine){ func RegisterUtilityRoutes(r *gin.Engine) {
registerRing(r) registerRing(r)
} }
func registerRing(r *gin.Engine){ func registerRing(r *gin.Engine) {
// Ping test // Ping test
r.GET("/ping", func(c *gin.Context) { r.GET("/ping", func(c *gin.Context) {
c.String(200, "pong") c.String(200, "pong")

View File

@@ -1,11 +0,0 @@
package contact
import (
"fmt"
)
func ContactService(ch chan string) {
for msg := range ch {
fmt.Println("Contact Service: ", msg)
}
}

View File

@@ -0,0 +1,28 @@
package contract
import (
"fmt"
"github.com/jinzhu/gorm"
"gitlab.com/pactual1/backend/shared"
)
type service struct {
ch chan string
db *gorm.DB
encryptionClient shared.EncryptionClient
}
func NewService(ch chan string, db *gorm.DB, encryptionClient shared.EncryptionClient) service {
return service{
ch: ch,
db: db,
encryptionClient: encryptionClient,
}
}
func (s service) ContractService() {
for msg := range s.ch {
fmt.Println("Contract Service: ", msg)
}
}

View File

@@ -11,36 +11,32 @@ import (
_ "github.com/jinzhu/gorm/dialects/postgres" _ "github.com/jinzhu/gorm/dialects/postgres"
) )
var db *gorm.DB var db *gorm.DB
var err error
func Init() error {
func Init() error{ host := config.AppConfig.Database.HostName
host := config.AppConfig.Database.HostName user := config.AppConfig.Database.UserName
user := config.AppConfig.Database.UserName
// port := config.AppConfig.Database.Port // port := config.AppConfig.Database.Port
dbName := config.AppConfig.Database.DatabaseName dbName := config.AppConfig.Database.DatabaseName
password := config.AppConfig.Database.Password password := config.AppConfig.Database.Password
dbString:= fmt.Sprintf("host=%s user=%s dbname=%s sslmode=disable password=%s",host,user,dbName,password) dbString := fmt.Sprintf("host=%s user=%s dbname=%s sslmode=disable password=%s", host, user, dbName, password)
// db, err = gorm.Open("postgres", "host=localhost user=postgres dbname=postgres sslmode=disable password=root") // db, err = gorm.Open("postgres", "host=localhost user=postgres dbname=postgres sslmode=disable password=root")
var err error var err error
// //PostgreSQL // //PostgreSQL
db, err = gorm.Open("postgres",dbString) db, err = gorm.Open("postgres", dbString)
if err != nil { if err != nil {
log.Println("Error initializing the database: ", err) log.Println("Error initializing the database: ", err)
return err return err
} }
//TODO AUTOMIGRATE models once we have them //TODO AUTOMIGRATE models once we have them
db.AutoMigrate(&models.User{}, &models.Company{}, &models.Device{}, &models.DeviceInfo{}) db.AutoMigrate(&models.User{}, &models.Company{}, &models.Device{}, &models.DeviceInfo{}, &models.Contract{}, &models.ContractInfo{})
return nil return nil
} }
func GetDb() *gorm.DB { func GetDb() *gorm.DB {
return db return db
} }

88
shared/encryption.go Normal file
View File

@@ -0,0 +1,88 @@
package shared
import (
"bytes"
"compress/flate"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
)
type EncryptionClient interface {
Encrypt(string) (string, error)
Decrypt(string) (string, error)
}
type encryptionClient struct {
Secret string
}
func NewEncryptionClient(secret string) EncryptionClient {
return &encryptionClient{Secret: secret}
}
func compress(text string) ([]byte, error) {
var compressedBytes bytes.Buffer
w, err := flate.NewWriter(&compressedBytes, flate.BestCompression)
w.Write([]byte(text))
w.Close()
return compressedBytes.Bytes(), err
}
func decompress(compressedBytes []byte) (string, error) {
reader := flate.NewReader(bytes.NewReader(compressedBytes))
defer reader.Close()
textBytes := new(bytes.Buffer)
_, err := textBytes.ReadFrom(reader)
return textBytes.String(), err
}
// Encrypt method is to encrypt or hide any classified text
func (e encryptionClient) Encrypt(text string) (string, error) {
block, err := aes.NewCipher([]byte(e.Secret))
if err != nil {
return "", err
}
compressedText, err := compress(text)
if err != nil {
return "", err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", err
}
bytes := make([]byte, gcm.NonceSize())
if _, err = io.ReadFull(rand.Reader, bytes); err != nil {
return "", err
}
encodedText := gcm.Seal(bytes, bytes, compressedText, nil)
return base64.StdEncoding.EncodeToString(encodedText), nil
}
// Decrypt method is to extract back the encrypted text
func (e encryptionClient) Decrypt(text string) (string, error) {
block, err := aes.NewCipher([]byte(e.Secret))
if err != nil {
return "", err
}
cipherText, err := base64.StdEncoding.DecodeString(text)
if err != nil {
return "", err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", err
}
if len(cipherText) < gcm.NonceSize() {
return "", fmt.Errorf("text is too small")
}
bytes, cipherText := cipherText[:gcm.NonceSize()], cipherText[gcm.NonceSize():]
compressedTextBytes, err := gcm.Open(nil, bytes, cipherText, nil)
if err != nil {
return "", err
}
return decompress(compressedTextBytes)
}

22
shared/encryption_test.go Normal file
View File

@@ -0,0 +1,22 @@
package shared
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestEncryptionClient(t *testing.T) {
client := encryptionClient{Secret: `abc&1*~#^2^#s0^=)^^7%b34`}
t.Run("encrypt/ decyrpt works", func(t *testing.T) {
text := "sample text to test encryption"
encodedText, err := client.Encrypt(text)
assert.NoError(t, err)
assert.NotEqual(t, text, encodedText)
decodedText, err := client.Decrypt(encodedText)
assert.NoError(t, err)
assert.Equal(t, text, decodedText)
})
}

View File

@@ -5,6 +5,6 @@
package shared package shared
const ( const (
RoleAdmin string = "admin" RoleAdmin string = "admin"
RoleProUser string = "pro-user" RoleProUser string = "pro-user"
) )