From e701f4701ba59b4bf206a559629cd0a846617fe4 Mon Sep 17 00:00:00 2001 From: Gaurav Mishra Date: Tue, 5 Dec 2023 18:19:13 +0530 Subject: [PATCH] fix(db): fix DB schema types 1. Update LicenseDB type to match the FOSSology DB Schema. 2. Update the gorm where queries to use struct making future code refactoring easy. 3. Made typo corrections and better code comments. Signed-off-by: Gaurav Mishra --- .gitignore | 4 + cmd/laas/main.go | 3 +- go.sum | 18 +++++ pkg/api/api.go | 180 ++++++++++++++++++++++++++++++-------------- pkg/api/api_test.go | 58 +++++++------- pkg/db/db.go | 16 +++- pkg/models/types.go | 108 +++++++++++++------------- pkg/utils/util.go | 83 ++++++++++++++++---- 8 files changed, 311 insertions(+), 159 deletions(-) diff --git a/.gitignore b/.gitignore index a5f8400..e96c94c 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,7 @@ # Go workspace file go.work licenseRef.json + +# IDE related files +/.idea +/LicenseDb.iml diff --git a/cmd/laas/main.go b/cmd/laas/main.go index 48fd058..8a070bf 100644 --- a/cmd/laas/main.go +++ b/cmd/laas/main.go @@ -5,11 +5,10 @@ package main import ( "flag" - "log" - "github.com/fossology/LicenseDb/pkg/api" "github.com/fossology/LicenseDb/pkg/db" "github.com/fossology/LicenseDb/pkg/models" + "log" ) // declare flags to input the basic requirement of database connection and the path of the data file diff --git a/go.sum b/go.sum index fcfb185..06726f2 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,7 @@ github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZX github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -15,6 +16,7 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= @@ -23,9 +25,11 @@ github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= @@ -33,6 +37,8 @@ github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/ github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU= github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= +github.com/jackc/puddle/v2 v2.2.0 h1:RdcDk92EJBuBS55nQMMYFXTxwstHug4jkhT5pq8VxPk= +github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= @@ -43,6 +49,7 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= @@ -62,6 +69,7 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -80,14 +88,22 @@ golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= 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/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 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= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= @@ -95,6 +111,7 @@ google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cn google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -102,4 +119,5 @@ gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0= gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8= gorm.io/gorm v1.25.1 h1:nsSALe5Pr+cM3V1qwwQ7rOkw+6UeLrX5O4v3llhHa64= gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/pkg/api/api.go b/pkg/api/api.go index 9a0329c..23a8c41 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -96,7 +96,7 @@ func GetAllLicense(c *gin.Context) { // Get license functions return data of the particular license by its shortname. // It inputs the shortname as query parameter -// It returns error ehen no such license exists +// It returns error if no such license exists func GetLicense(c *gin.Context) { var license models.LicenseDB @@ -105,11 +105,11 @@ func GetLicense(c *gin.Context) { return } - err := db.DB.Where("shortname = ?", queryParam).First(&license).Error + err := db.DB.Where(models.LicenseDB{Shortname: queryParam}).First(&license).Error if err != nil { er := models.LicenseError{ - Status: http.StatusBadRequest, + Status: http.StatusNotFound, Message: fmt.Sprintf("no license with shortname '%s' exists", queryParam), Error: err.Error(), Path: c.Request.URL.Path, @@ -131,7 +131,7 @@ func GetLicense(c *gin.Context) { } // The Create License function creates license in the database and add the required data -// It return the license if it already exists in the database +// It returns the license if it already exists in the database. func CreateLicense(c *gin.Context) { var input models.LicenseInput @@ -147,9 +147,6 @@ func CreateLicense(c *gin.Context) { return } - if input.Active == "" { - input.Active = "t" - } license := models.LicenseDB{ Shortname: input.Shortname, Fullname: input.Fullname, @@ -219,7 +216,7 @@ func UpdateLicense(c *gin.Context) { username := c.GetString("username") shortname := c.Param("shortname") - if err := db.DB.Where("shortname = ?", shortname).First(&license).Error; err != nil { + if err := db.DB.Where(models.LicenseDB{Shortname: shortname}).First(&license).Error; err != nil { er := models.LicenseError{ Status: http.StatusBadRequest, Message: fmt.Sprintf("license with shortname '%s' not found", shortname), @@ -263,11 +260,11 @@ func UpdateLicense(c *gin.Context) { } var user models.User - db.DB.Where("username = ?", username).First(&user) + db.DB.Where(models.User{Username: username}).First(&user) audit := models.Audit{ UserId: user.Id, TypeId: license.Id, - Timestamp: time.Now().Format(time.RFC3339), + Timestamp: time.Now(), Type: "license", } @@ -304,8 +301,8 @@ func UpdateLicense(c *gin.Context) { change := models.ChangeLog{ AuditId: audit.Id, Field: "Adddate", - OldValue: oldlicense.AddDate, - UpdatedValue: license.AddDate, + OldValue: oldlicense.AddDate.Format(time.RFC3339), + UpdatedValue: license.AddDate.Format(time.RFC3339), } db.DB.Create(&change) } @@ -313,8 +310,8 @@ func UpdateLicense(c *gin.Context) { change := models.ChangeLog{ AuditId: audit.Id, Field: "Active", - OldValue: oldlicense.Active, - UpdatedValue: license.Active, + OldValue: strconv.FormatBool(oldlicense.Active), + UpdatedValue: strconv.FormatBool(license.Active), } db.DB.Create(&change) } @@ -322,8 +319,8 @@ func UpdateLicense(c *gin.Context) { change := models.ChangeLog{ AuditId: audit.Id, Field: "Copyleft", - OldValue: oldlicense.Copyleft, - UpdatedValue: license.Copyleft, + OldValue: strconv.FormatBool(oldlicense.Copyleft), + UpdatedValue: strconv.FormatBool(license.Copyleft), } db.DB.Create(&change) } @@ -331,8 +328,8 @@ func UpdateLicense(c *gin.Context) { change := models.ChangeLog{ AuditId: audit.Id, Field: "FSFfree", - OldValue: oldlicense.FSFfree, - UpdatedValue: license.FSFfree, + OldValue: strconv.FormatBool(oldlicense.FSFfree), + UpdatedValue: strconv.FormatBool(license.FSFfree), } db.DB.Create(&change) } @@ -340,8 +337,8 @@ func UpdateLicense(c *gin.Context) { change := models.ChangeLog{ AuditId: audit.Id, Field: "GPLv2compatible", - OldValue: oldlicense.GPLv2compatible, - UpdatedValue: license.GPLv2compatible, + OldValue: strconv.FormatBool(oldlicense.GPLv2compatible), + UpdatedValue: strconv.FormatBool(license.GPLv2compatible), } db.DB.Create(&change) } @@ -349,8 +346,8 @@ func UpdateLicense(c *gin.Context) { change := models.ChangeLog{ AuditId: audit.Id, Field: "GPLv3compatible", - OldValue: oldlicense.GPLv3compatible, - UpdatedValue: license.GPLv3compatible, + OldValue: strconv.FormatBool(oldlicense.GPLv3compatible), + UpdatedValue: strconv.FormatBool(license.GPLv3compatible), } db.DB.Create(&change) } @@ -376,8 +373,8 @@ func UpdateLicense(c *gin.Context) { change := models.ChangeLog{ AuditId: audit.Id, Field: "TextUpdatable", - OldValue: oldlicense.TextUpdatable, - UpdatedValue: license.TextUpdatable, + OldValue: strconv.FormatBool(oldlicense.TextUpdatable), + UpdatedValue: strconv.FormatBool(license.TextUpdatable), } db.DB.Create(&change) } @@ -412,8 +409,8 @@ func UpdateLicense(c *gin.Context) { change := models.ChangeLog{ AuditId: audit.Id, Field: "DetectorType", - OldValue: oldlicense.DetectorType, - UpdatedValue: license.DetectorType, + OldValue: strconv.FormatInt(oldlicense.DetectorType, 10), + UpdatedValue: strconv.FormatInt(license.DetectorType, 10), } db.DB.Create(&change) } @@ -439,8 +436,8 @@ func UpdateLicense(c *gin.Context) { change := models.ChangeLog{ AuditId: audit.Id, Field: "Risk", - OldValue: oldlicense.Risk, - UpdatedValue: license.Risk, + OldValue: strconv.FormatInt(oldlicense.Risk, 10), + UpdatedValue: strconv.FormatInt(license.Risk, 10), } db.DB.Create(&change) } @@ -448,8 +445,8 @@ func UpdateLicense(c *gin.Context) { change := models.ChangeLog{ AuditId: audit.Id, Field: "Marydone", - OldValue: oldlicense.Marydone, - UpdatedValue: license.Marydone, + OldValue: strconv.FormatBool(oldlicense.Marydone), + UpdatedValue: strconv.FormatBool(license.Marydone), } db.DB.Create(&change) } @@ -477,39 +474,79 @@ func FilterLicense(c *gin.Context) { return } if active != "" { - query = query.Where("active=?", active) + parsedActive, err := strconv.ParseBool(active) + if err != nil { + parsedActive = false + } + query = query.Where(models.LicenseDB{Active: parsedActive}) } if fsffree != "" { - query = query.Where("fs_ffree=?", fsffree) + parsedFsffree, err := strconv.ParseBool(fsffree) + if err != nil { + parsedFsffree = false + } + query = query.Where(models.LicenseDB{FSFfree: parsedFsffree}) } if OSIapproved != "" { - query = query.Where("os_iapproved=?", OSIapproved) + parsedOsiApproved, err := strconv.ParseBool(OSIapproved) + if err != nil { + parsedOsiApproved = false + } + query = query.Where(models.LicenseDB{OSIapproved: parsedOsiApproved}) } if copyleft != "" { - query = query.Where("copyleft=?", copyleft) + parsedCopyleft, err := strconv.ParseBool(copyleft) + if err != nil { + parsedCopyleft = false + } + query = query.Where(models.LicenseDB{Copyleft: parsedCopyleft}) } if SpdxId != "" { - query = query.Where("spdx_id=?", SpdxId) + query = query.Where(models.LicenseDB{SpdxId: SpdxId}) } if DetectorType != "" { - query = query.Where("detector_type=?", DetectorType) + parsedDetectorType, err := strconv.ParseInt(DetectorType, 10, 64) + if err != nil { + er := models.LicenseError{ + Status: http.StatusBadRequest, + Message: "Invalid detector type value", + Error: err.Error(), + Path: c.Request.URL.Path, + Timestamp: time.Now().Format(time.RFC3339), + } + c.JSON(http.StatusBadRequest, er) + return + } + query = query.Where(models.LicenseDB{DetectorType: parsedDetectorType}) } if GPLv2compatible != "" { - query = query.Where("gp_lv2compatible=?", GPLv2compatible) + parsedGPLv2compatible, err := strconv.ParseBool(GPLv2compatible) + if err != nil { + parsedGPLv2compatible = false + } + query = query.Where(models.LicenseDB{GPLv2compatible: parsedGPLv2compatible}) } if GPLv3compatible != "" { - query = query.Where("gp_lv3compatible=?", GPLv3compatible) + parsedGPLv3compatible, err := strconv.ParseBool(GPLv3compatible) + if err != nil { + parsedGPLv3compatible = false + } + query = query.Where(models.LicenseDB{GPLv3compatible: parsedGPLv3compatible}) } if marydone != "" { - query = query.Where("marydone=?", marydone) + parsedMarydone, err := strconv.ParseBool(marydone) + if err != nil { + parsedMarydone = false + } + query = query.Where(models.LicenseDB{Marydone: parsedMarydone}) } if err := query.Error; err != nil { @@ -617,10 +654,14 @@ func GetAllAudit(c *gin.Context) { // GetAudit retrieves a specific audit record by its ID from the database and responds // with JSON containing the audit data or an error message if the record is not found. func GetAudit(c *gin.Context) { - var chngelog models.Audit + var changelog models.Audit id := c.Param("audit_id") + parsedId, err := parseId(c, id, "audit") + if err != nil { + return + } - if err := db.DB.Where("id = ?", id).First(&chngelog).Error; err != nil { + if err := db.DB.Where(models.Audit{Id: parsedId}).First(&changelog).Error; err != nil { er := models.LicenseError{ Status: http.StatusBadRequest, Message: "no change log with such id exists", @@ -631,7 +672,7 @@ func GetAudit(c *gin.Context) { c.JSON(http.StatusBadRequest, er) } res := models.AuditResponse{ - Data: []models.Audit{chngelog}, + Data: []models.Audit{changelog}, Status: http.StatusOK, Meta: models.PaginationMeta{ ResourceCount: 1, @@ -641,14 +682,34 @@ func GetAudit(c *gin.Context) { c.JSON(http.StatusOK, res) } +func parseId(c *gin.Context, id string, idType string) (int, error) { + parsedId, err := strconv.Atoi(id) + if err != nil { + er := models.LicenseError{ + Status: http.StatusBadRequest, + Message: fmt.Sprintf("invalid %s id", idType), + Error: err.Error(), + Path: c.Request.URL.Path, + Timestamp: time.Now().Format(time.RFC3339), + } + c.JSON(http.StatusBadRequest, er) + return 0, err + } + return parsedId, nil +} + // GetChangeLog retrieves a list of change history records associated with a specific // audit by its audit ID from the database and responds with JSON containing the change // history data or an error message if no records are found. func GetChangeLog(c *gin.Context) { var changelog []models.ChangeLog id := c.Param("audit_id") + parsedId, err := parseId(c, id, "audit") + if err != nil { + return + } - if err := db.DB.Where("audit_id = ?", id).Find(&changelog).Error; err != nil { + if err := db.DB.Where(models.ChangeLog{AuditId: parsedId}).Find(&changelog).Error; err != nil { er := models.LicenseError{ Status: http.StatusBadRequest, Message: "no change log with such id exists", @@ -675,10 +736,18 @@ func GetChangeLog(c *gin.Context) { // is not found or if it does not belong to the specified audit. func GetChangeLogbyId(c *gin.Context) { var changelog models.ChangeLog - auditid := c.Param("audit_id") - id := c.Param("id") + auditId := c.Param("audit_id") + parsedAuditId, err := parseId(c, auditId, "audit") + if err != nil { + return + } + changelogId := c.Param("id") + parsedChangeLogId, err := parseId(c, changelogId, "change log") + if err != nil { + return + } - if err := db.DB.Where("id = ?", id).Find(&changelog).Error; err != nil { + if err := db.DB.Where(models.ChangeLog{Id: parsedChangeLogId}).Find(&changelog).Error; err != nil { er := models.LicenseError{ Status: http.StatusBadRequest, Message: "no change history with such id exists", @@ -688,8 +757,7 @@ func GetChangeLogbyId(c *gin.Context) { } c.JSON(http.StatusBadRequest, er) } - audit_id, _ := strconv.Atoi(auditid) - if changelog.AuditId != audit_id { + if changelog.AuditId != parsedAuditId { er := models.LicenseError{ Status: http.StatusBadRequest, Message: "no change history with such id and audit id exists", @@ -776,7 +844,7 @@ func CreateObligation(c *gin.Context) { } for _, i := range input.Shortnames { var license models.LicenseDB - db.DB.Where("shortname = ?", i).Find(&license) + db.DB.Where(models.LicenseDB{Shortname: i}).Find(&license) obmap := models.ObligationMap{ ObligationPk: obligation.Id, RfPk: license.Id, @@ -800,7 +868,7 @@ func CreateObligation(c *gin.Context) { func GetAllObligation(c *gin.Context) { var obligations []models.Obligation query := db.DB.Model(&obligations) - query = query.Where("active=?", true) + query = query.Where(models.Obligation{Active: true}) err := query.Find(&obligations).Error if err != nil { er := models.LicenseError{ @@ -835,9 +903,8 @@ func UpdateObligation(c *gin.Context) { username := c.GetString("username") query := db.DB.Model(&obligation) - query = query.Where("active=?", true) tp := c.Param("topic") - if err := query.Where("topic = ?", tp).First(&obligation).Error; err != nil { + if err := query.Where(models.Obligation{Active: true, Topic: tp}).First(&obligation).Error; err != nil { er := models.LicenseError{ Status: http.StatusBadRequest, Message: fmt.Sprintf("obligation with topic '%s' not found", tp), @@ -873,11 +940,11 @@ func UpdateObligation(c *gin.Context) { } var user models.User - db.DB.Where("username = ?", username).First(&user) + db.DB.Where(models.User{Username: username}).First(&user) audit := models.Audit{ UserId: user.Id, TypeId: obligation.Id, - Timestamp: time.Now().Format(time.RFC3339), + Timestamp: time.Now(), Type: "Obligation", } db.DB.Create(&audit) @@ -990,7 +1057,7 @@ func UpdateObligation(c *gin.Context) { func DeleteObligation(c *gin.Context) { var obligation models.Obligation tp := c.Param("topic") - if err := db.DB.Where("topic= ?", tp).First(&obligation).Error; err != nil { + if err := db.DB.Where(models.Obligation{Topic: tp}).First(&obligation).Error; err != nil { er := models.LicenseError{ Status: http.StatusBadRequest, Message: fmt.Sprintf("obligation with topic '%s' not found", tp), @@ -1010,9 +1077,8 @@ func DeleteObligation(c *gin.Context) { func GetObligation(c *gin.Context) { var obligation models.Obligation query := db.DB.Model(&obligation) - query = query.Where("active=?", true) tp := c.Param("topic") - if err := query.Where("topic= ?", tp).First(&obligation).Error; err != nil { + if err := query.Where(models.Obligation{Active: true, Topic: tp}).First(&obligation).Error; err != nil { er := models.LicenseError{ Status: http.StatusBadRequest, Message: fmt.Sprintf("obligation with topic '%s' not found", tp), diff --git a/pkg/api/api_test.go b/pkg/api/api_test.go index 2d2a6a4..8a61c0a 100644 --- a/pkg/api/api_test.go +++ b/pkg/api/api_test.go @@ -53,11 +53,11 @@ func TestGetLicense(t *testing.T) { Fullname: "MIT License", Text: "MIT License\n\nCopyright (c) \n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", Url: "https://opensource.org/licenses/MIT", - TextUpdatable: "f", - DetectorType: "1", - Active: "t", - Flag: "1", - Marydone: "t", + TextUpdatable: false, + DetectorType: 1, + Active: true, + Flag: 1, + Marydone: true, SpdxId: "MIT", } w := makeRequest("GET", "/api/licenses/MIT", nil, false) @@ -77,9 +77,9 @@ func TestCreateLicense(t *testing.T) { Text: "just a license", Url: "https://abcdlicense/ABCD", SpdxId: "1", - TextUpdatable: "f", - DetectorType: "1", - Active: "t", + TextUpdatable: false, + DetectorType: 1, + Active: true, } w := makeRequest("POST", "/api/licenses", License, true) assert.Equal(t, http.StatusCreated, w.Code) @@ -96,18 +96,18 @@ func TestCreateLicense(t *testing.T) { func TestUpdateLicense(t *testing.T) { License := models.LicenseDB{ - Marydone: "t", + Marydone: true, } expectedLicense := models.LicenseDB{ Shortname: "MIT", Fullname: "MIT License", Text: "MIT License\n\nCopyright (c) \n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", Url: "https://opensource.org/licenses/MIT", - TextUpdatable: "f", - DetectorType: "1", - Active: "t", - Flag: "1", - Marydone: "t", + TextUpdatable: false, + DetectorType: 1, + Active: true, + Flag: 1, + Marydone: true, SpdxId: "MIT", } w := makeRequest("PATCH", "/api/licenses/MIT", License, true) @@ -126,11 +126,11 @@ func TestSearchInLicense(t *testing.T) { Fullname: "PostgreSQL License", Text: "PostgreSQL Database Management System\n(formerly known as Postgres, then as Postgres95)\n\nPortions Copyright (c) 1996-2010, The PostgreSQL Global Development Group\n\nPortions Copyright (c) 1994, The Regents of the University of California\n\nPermission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies.\n\nIN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nTHE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN \"AS IS\" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\n", Url: "http://www.postgresql.org/about/licence", - TextUpdatable: "f", - DetectorType: "1", - Active: "t", - Flag: "1", - Marydone: "f", + TextUpdatable: false, + DetectorType: 1, + Active: true, + Flag: 1, + Marydone: false, SpdxId: "PostgreSQL", } search := models.SearchLicense{ @@ -156,11 +156,11 @@ func TestSearchInLicense2(t *testing.T) { Text: "insert GPL v2 license text here\n\nAutoconf Exception\n\nAs a special exception, the Free Software Foundation gives unlimited permission to copy, distribute and modify the configure scripts that are the output of Autoconf. You need not follow the terms of the GNU General Public License when using or distributing such scripts, even though portions of the text of Autoconf appear in them. The GNU General Public License (GPL) does govern all other use of the material that constitutes the Autoconf program.\n\nCertain portions of the Autoconf source text are designed to be copied (in certain cases, depending on the input) into the output of Autoconf. We call these the \"data\" portions. The rest of the Autoconf source text consists of comments plus executable code that decides which of the data portions to output in any given case. We call these comments and executable code the \"non-data\" portions. Autoconf never copies any of the non-data portions into its output.\n\nThis special exception to the GPL applies to versions of Autoconf released by the Free Software Foundation. When you make and distribute a modified version of Autoconf, you may extend this special exception to the GPL to apply to your modified version as well, *unless* your modified version has the potential to copy into its output some of the text that was the non-data portion of the version that you started with. (In other words, unless your change moves or copies text from the non-data portions to the data portions.) If your modification has such potential, you must delete any notice of this special exception to the GPL from your modified version.\n\n", Url: "http://ac-archive.sourceforge.net/doc/copyright.html", Notes: "DEPRECATED: Use license expression including main license, \"WITH\" operator, and identifier: Autoconf-exception-2.0", - TextUpdatable: "f", - DetectorType: "1", - Active: "t", - Flag: "1", - Marydone: "f", + TextUpdatable: false, + DetectorType: 1, + Active: true, + Flag: 1, + Marydone: false, SpdxId: "LicenseRef-fossology-GPL-2.0-with-autoconf-exception", }, { @@ -169,11 +169,11 @@ func TestSearchInLicense2(t *testing.T) { Text: "As a special exception, the Free Software Foundation gives unlimited permission to copy, distribute and modify the configure scripts that are the output of Autoconf. You need not follow the terms of the GNU General Public License when using or distributing such scripts, even though portions of the text of Autoconf appear in them. The GNU General Public License (GPL) does govern all other use of the material that constitutes the Autoconf program.\n\nCertain portions of the Autoconf source text are designed to be copied (in certain cases, depending on the input) into the output of Autoconf. We call these the \"data\" portions. The rest of the Autoconf source text consists of comments plus executable code that decides which of the data portions to output in any given case. We call these comments and executable code the \"non-data\" portions. Autoconf never copies any of the non-data portions into its output.\n\nThis special exception to the GPL applies to versions of Autoconf released by the Free Software Foundation. When you make and distribute a modified version of Autoconf, you may extend this special exception to the GPL to apply to your modified version as well, *unless* your modified version has the potential to copy into its output some of the text that was the non-data portion of the version that you started with. (In other words, unless your change moves or copies text from the non-data portions to the data portions.) If your modification has such potential, you must delete any notice of this special exception to the GPL from your modified version.\n", Url: "http://ac-archive.sourceforge.net/doc/copyright.html", Notes: "Typically used with GPL-2.0", - TextUpdatable: "f", - DetectorType: "1", - Active: "t", - Flag: "1", - Marydone: "f", + TextUpdatable: false, + DetectorType: 1, + Active: true, + Flag: 1, + Marydone: false, SpdxId: "Autoconf-exception-2.0", }, } diff --git a/pkg/db/db.go b/pkg/db/db.go index 7b8713b..8b58f2a 100644 --- a/pkg/db/db.go +++ b/pkg/db/db.go @@ -6,8 +6,8 @@ package db import ( "encoding/json" "fmt" - "io/ioutil" "log" + "os" "github.com/fossology/LicenseDb/pkg/models" "github.com/fossology/LicenseDb/pkg/utils" @@ -36,15 +36,23 @@ func Populatedb(populatedb bool, datafile string) { if populatedb { var licenses []models.LicenseJson // Read the content of the data file. - byteResult, _ := ioutil.ReadFile(datafile) + byteResult, err := os.ReadFile(datafile) + if err != nil { + log.Fatalf("Unable to read JSON file: %v", err) + } // Unmarshal the JSON file data into a slice of LicenseJson structs. if err := json.Unmarshal(byteResult, &licenses); err != nil { log.Fatalf("error reading from json file: %v", err) } for _, license := range licenses { - // populate the data in the database table + // Create the license if it does not already exist in the database. + // Otherwise, update the license if flag is 1. result := utils.Converter(license) - DB.Create(&result) + err := DB.Where(models.LicenseDB{Shortname: result.Shortname, Flag: 1}).Assign(result). + FirstOrCreate(&result).Error + if err != nil { + log.Fatalf("error creating license: %v", err) + } } } } diff --git a/pkg/models/types.go b/pkg/models/types.go index 4667b1a..32a344a 100644 --- a/pkg/models/types.go +++ b/pkg/models/types.go @@ -3,31 +3,33 @@ package models -// The License struct represents a license entity with various attributes and +import "time" + +// The LicenseDB struct represents a license entity with various attributes and // properties associated with it. // It provides structured storage for license-related information. type LicenseDB struct { - Id int64 `json:"rf_id" gorm:"primary_key"` - Shortname string `json:"rf_shortname"` - Fullname string `json:"rf_fullname"` - Text string `json:"rf_text"` - Url string `json:"rf_url"` - AddDate string `json:"rf_add_date"` - Copyleft string `json:"rf_copyleft"` - FSFfree string `json:"rf_FSFfree"` - OSIapproved string `json:"rf_OSIapproved"` - GPLv2compatible string `json:"rf_GPLv2compatible"` - GPLv3compatible string `json:"rf_GPLv3compatible"` - Notes string `json:"rf_notes"` - Fedora string `json:"rf_Fedora"` - TextUpdatable string `json:"rf_text_updatable"` - DetectorType string `json:"rf_detector_type"` - Active string `json:"rf_active"` - Source string `json:"rf_source"` - SpdxId string `json:"rf_spdx_id"` - Risk string `json:"rf_risk"` - Flag string `json:"rf_flag"` - Marydone string `json:"marydone"` + Id int64 `json:"rf_id" gorm:"primary_key"` + Shortname string `json:"rf_shortname" gorm:"unique;not null" binding:"required"` + Fullname string `json:"rf_fullname"` + Text string `json:"rf_text"` + Url string `json:"rf_url"` + AddDate time.Time `json:"rf_add_date" gorm:"default:CURRENT_TIMESTAMP"` + Copyleft bool `json:"rf_copyleft"` + FSFfree bool `json:"rf_FSFfree"` + OSIapproved bool `json:"rf_OSIapproved"` + GPLv2compatible bool `json:"rf_GPLv2compatible"` + GPLv3compatible bool `json:"rf_GPLv3compatible"` + Notes string `json:"rf_notes"` + Fedora string `json:"rf_Fedora"` + TextUpdatable bool `json:"rf_text_updatable"` + DetectorType int64 `json:"rf_detector_type"` + Active bool `json:"rf_active"` + Source string `json:"rf_source"` + SpdxId string `json:"rf_spdx_id"` + Risk int64 `json:"rf_risk"` + Flag int64 `json:"rf_flag" gorm:"default:1"` + Marydone bool `json:"marydone"` } type LicenseJson struct { @@ -44,7 +46,7 @@ type LicenseJson struct { Notes string `json:"rf_notes"` Fedora string `json:"rf_Fedora"` TextUpdatable string `json:"rf_text_updatable"` - DetectorType string `json:"rf_detector_type"` + DetectorType int64 `json:"rf_detector_type"` Active string `json:"rf_active"` Source string `json:"rf_source"` SpdxCompatible string `json:"rf_spdx_compatible"` @@ -53,7 +55,7 @@ type LicenseJson struct { Marydone string `json:"marydone"` } -// The Meta struct represents additional metadata associated with a +// The PaginationMeta struct represents additional metadata associated with a // license retrieval operation. // It contains information that provides context and supplementary details // about the retrieved license data. @@ -87,34 +89,34 @@ type LicenseError struct { // The LicenseInput struct represents the input or payload required for creating a license. // It contains various fields that capture the necessary information for defining a license entity. type LicenseInput struct { - Shortname string `json:"rf_shortname" binding:"required"` - Fullname string `json:"rf_fullname" binding:"required"` - Text string `json:"rf_text" binding:"required"` - Url string `json:"rf_url"` - AddDate string `json:"rf_add_date"` - Copyleft string `json:"rf_copyleft"` - FSFfree string `json:"rf_FSFfree"` - OSIapproved string `json:"rf_OSIapproved"` - GPLv2compatible string `json:"rf_GPLv2compatible"` - GPLv3compatible string `json:"rf_GPLv3compatible"` - Notes string `json:"rf_notes"` - Fedora string `json:"rf_Fedora"` - TextUpdatable string `json:"rf_text_updatable"` - DetectorType string `json:"rf_detector_type"` - Active string `json:"rf_active"` - Source string `json:"rf_source"` - SpdxId string `json:"rf_spdx_id" binding:"required"` - Risk string `json:"rf_risk"` - Flag string `json:"rf_flag"` - Marydone string `json:"marydone"` + Shortname string `json:"rf_shortname"` + Fullname string `json:"rf_fullname"` + Text string `json:"rf_text"` + Url string `json:"rf_url"` + AddDate time.Time `json:"rf_add_date"` + Copyleft bool `json:"rf_copyleft"` + FSFfree bool `json:"rf_FSFfree"` + OSIapproved bool `json:"rf_OSIapproved"` + GPLv2compatible bool `json:"rf_GPLv2compatible"` + GPLv3compatible bool `json:"rf_GPLv3compatible"` + Notes string `json:"rf_notes"` + Fedora string `json:"rf_Fedora"` + TextUpdatable bool `json:"rf_text_updatable"` + DetectorType int64 `json:"rf_detector_type"` + Active bool `json:"rf_active"` + Source string `json:"rf_source"` + SpdxId string `json:"rf_spdx_id"` + Risk int64 `json:"rf_risk"` + Flag int64 `json:"rf_flag"` + Marydone bool `json:"marydone"` } // User struct is representation of user information. type User struct { Id int64 `json:"id" gorm:"primary_key"` - Username string `json:"username" gorm:"unique" binding:"required"` - Userlevel string `json:"userlevel" gorm:"unique" binding:"required"` - Userpassword string `json:"userpassword" gorm:"unique" binding:"required"` + Username string `json:"username" gorm:"unique;not null" binding:"required"` + Userlevel string `json:"userlevel" binding:"required"` + Userpassword string `json:"userpassword" binding:"required"` } // UserResponse struct is representation of design API response of user. @@ -134,12 +136,12 @@ type SearchLicense struct { // Audit struct represents an audit entity with certain attributes and properties // It has user id as a foreign key type Audit struct { - Id int `json:"id" gorm:"primary_key"` - UserId int64 `json:"user_id"` - User User `gorm:"foreignKey:UserId;references:Id" json:"-"` - TypeId int64 `json:"type_id"` - Timestamp string `json:"timestamp"` - Type string `json:"type"` + Id int `json:"id" gorm:"primary_key"` + UserId int64 `json:"user_id"` + User User `gorm:"foreignKey:UserId;references:Id" json:"-"` + TypeId int64 `json:"type_id"` + Timestamp time.Time `json:"timestamp"` + Type string `json:"type"` } // ChangeLog struct represents a change entity with certain attributes and properties diff --git a/pkg/utils/util.go b/pkg/utils/util.go index 9bcff75..8cfc57c 100644 --- a/pkg/utils/util.go +++ b/pkg/utils/util.go @@ -3,7 +3,11 @@ package utils -import "github.com/fossology/LicenseDb/pkg/models" +import ( + "github.com/fossology/LicenseDb/pkg/models" + "strconv" + "time" +) // The Converter function takes an input of type models.LicenseJson and converts it into a // corresponding models.LicenseDB object. @@ -11,32 +15,83 @@ import "github.com/fossology/LicenseDb/pkg/models" // including generating the SpdxId based on the SpdxCompatible field. // The resulting LicenseDB object is returned as the output of this function. func Converter(input models.LicenseJson) models.LicenseDB { - if input.SpdxCompatible == "t" { + spdxCompatible, err := strconv.ParseBool(input.SpdxCompatible) + if err != nil { + spdxCompatible = false + } + if spdxCompatible { input.SpdxCompatible = input.Shortname } else { input.SpdxCompatible = "LicenseRef-fossology-" + input.Shortname } + + copyleft, err := strconv.ParseBool(input.Copyleft) + if err != nil { + copyleft = false + } + fsfFree, err := strconv.ParseBool(input.FSFfree) + if err != nil { + fsfFree = false + } + osiApproved, err := strconv.ParseBool(input.OSIapproved) + if err != nil { + osiApproved = false + } + gplv2Compatible, err := strconv.ParseBool(input.GPLv2compatible) + if err != nil { + gplv2Compatible = false + } + gplv3Compatible, err := strconv.ParseBool(input.GPLv3compatible) + if err != nil { + gplv3Compatible = false + } + textUpdatable, err := strconv.ParseBool(input.TextUpdatable) + if err != nil { + textUpdatable = false + } + active, err := strconv.ParseBool(input.Active) + if err != nil { + active = false + } + marydone, err := strconv.ParseBool(input.Marydone) + if err != nil { + marydone = false + } + addDate, err := time.Parse(time.RFC3339, input.AddDate) + if err != nil { + addDate = time.Now() + } + detectorType := input.DetectorType + risk, err := strconv.ParseInt(input.Risk, 10, 64) + if err != nil { + risk = 0 + } + flag, err := strconv.ParseInt(input.Flag, 10, 64) + if err != nil { + flag = 1 + } + result := models.LicenseDB{ Shortname: input.Shortname, Fullname: input.Fullname, Text: input.Text, Url: input.Url, - Copyleft: input.Copyleft, - AddDate: input.AddDate, - FSFfree: input.FSFfree, - OSIapproved: input.OSIapproved, - GPLv2compatible: input.GPLv2compatible, - GPLv3compatible: input.GPLv3compatible, + Copyleft: copyleft, + AddDate: addDate, + FSFfree: fsfFree, + OSIapproved: osiApproved, + GPLv2compatible: gplv2Compatible, + GPLv3compatible: gplv3Compatible, Notes: input.Notes, Fedora: input.Fedora, - TextUpdatable: input.TextUpdatable, - DetectorType: input.DetectorType, - Active: input.Active, + TextUpdatable: textUpdatable, + DetectorType: detectorType, + Active: active, Source: input.Source, SpdxId: input.SpdxCompatible, - Risk: input.Risk, - Flag: input.Flag, - Marydone: input.Marydone, + Risk: risk, + Flag: flag, + Marydone: marydone, } return result }