Skip to content

Commit

Permalink
feat: added authentication in API and search api
Browse files Browse the repository at this point in the history
	Get license with specific search term:
		field: represents the name of field to be searched
		search_term: represents the term to be searched
		search: represent the algorithm to search with

	authenticate the API:
		added the struct for user
		created a user table in the database
		added basic user endpoints:
			get user using id
			get all user
			create user
		added basic authentication to all the API endpoints i.e, group of endpoints

Signed-off-by: Kavya Shukla <kavyuushukla59@gmail.com>
  • Loading branch information
k-avy committed Jul 27, 2023
1 parent 750c059 commit 721d8f1
Show file tree
Hide file tree
Showing 8 changed files with 377 additions and 89 deletions.
49 changes: 7 additions & 42 deletions cmd/laas/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,12 @@
package main

import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"

"github.com/fossology/LicenseDb/pkg/api"
"github.com/fossology/LicenseDb/pkg/auth"
"github.com/fossology/LicenseDb/pkg/db"
"github.com/fossology/LicenseDb/pkg/models"
"github.com/fossology/LicenseDb/pkg/utils"
"github.com/gin-gonic/gin"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)

// declare flags to input the basic requirement of database connection and the path of the data file
Expand All @@ -40,46 +33,18 @@ var (
func main() {
flag.Parse()

dburi := fmt.Sprintf("host=%s port=%s user=%s dbname=%s password=%s", *dbhost, *port, *user, *dbname, *password)
gormConfig := &gorm.Config{}
database, err := gorm.Open(postgres.Open(dburi), gormConfig)
if err != nil {
log.Fatalf("Failed to connect to database: %v", err)
}
db.Connect(dbhost, port, user, dbname, password)

if err := database.AutoMigrate(&models.LicenseDB{}); err != nil {
if err := db.DB.AutoMigrate(&models.LicenseDB{}); err != nil {
log.Fatalf("Failed to automigrate database: %v", err)
}

if err := database.AutoMigrate(&models.User{}); err != nil {
if err := db.DB.AutoMigrate(&models.User{}); err != nil {
log.Fatalf("Failed to automigrate database: %v", err)
}
if *populatedb {
var licenses []models.LicenseJson
// read the file of data
byteResult, _ := ioutil.ReadFile(*datafile)
// unmarshal the json file and it into the struct format
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
result := utils.Converter(license)
database.Create(&result)
}
}
api.DB = database

r := gin.Default()
r.NoRoute(api.HandleInvalidUrl)
authorized := r.Group("/")
authorized.Use(auth.AuthenticationMiddleware())
authorized.GET("/api/license/:shortname", api.GetLicense)
authorized.POST("/api/license", api.CreateLicense)
authorized.PATCH("/api/license/update/:shortname", api.UpdateLicense)
authorized.GET("/api/licenses", api.SearchInLicense)
r.POST("/api/user", auth.CreateUser)
authorized.GET("/api/users", auth.GetAllUser)
authorized.GET("/api/user/:id", auth.GetUser)
db.Populatedb(*populatedb, *datafile)

r := api.Router()
r.Run()
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ go 1.20

require (
github.com/gin-gonic/gin v1.9.1
github.com/stretchr/testify v1.8.3
gorm.io/driver/postgres v1.5.2
gorm.io/gorm v1.25.1
)

require (
github.com/bytedance/sonic v1.9.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
Expand All @@ -30,6 +32,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
Expand Down
106 changes: 89 additions & 17 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,35 @@ import (
"net/http"
"time"

"github.com/fossology/LicenseDb/pkg/auth"
"github.com/fossology/LicenseDb/pkg/db"
"github.com/fossology/LicenseDb/pkg/models"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)

var DB *gorm.DB
func Router() *gin.Engine {
// r is a default instance of gin engine
r := gin.Default()

// return error for invalid routes
r.NoRoute(HandleInvalidUrl)

// authorization not required for these routes
r.GET("/api/license/:shortname", GetLicense)
r.GET("/api/licenses", SearchInLicense)
r.GET("/api/users", auth.GetAllUser)
r.GET("/api/user/:id", auth.GetUser)

// set up authentication
authorized := r.Group("/")
authorized.Use(auth.AuthenticationMiddleware())

authorized.POST("/api/license", CreateLicense)
authorized.PATCH("/api/license/update/:shortname", UpdateLicense)
authorized.POST("/api/user", auth.CreateUser)

return r
}

func HandleInvalidUrl(c *gin.Context) {

Expand All @@ -27,9 +50,10 @@ func HandleInvalidUrl(c *gin.Context) {
c.JSON(http.StatusNotFound, er)
}
func GetAllLicense(c *gin.Context) {

var licenses []models.LicenseDB

err := DB.Find(&licenses).Error
err := db.DB.Find(&licenses).Error
if err != nil {
er := models.LicenseError{
Status: http.StatusBadRequest,
Expand All @@ -44,7 +68,7 @@ func GetAllLicense(c *gin.Context) {
res := models.LicenseResponse{
Data: licenses,
Status: http.StatusOK,
Meta: models.Meta{
Meta: models.PaginationMeta{
ResourceCount: len(licenses),
},
}
Expand All @@ -60,7 +84,7 @@ func GetLicense(c *gin.Context) {
return
}

err := DB.Where("shortname = ?", queryParam).First(&license).Error
err := db.DB.Where("shortname = ?", queryParam).First(&license).Error

if err != nil {
er := models.LicenseError{
Expand All @@ -77,7 +101,7 @@ func GetLicense(c *gin.Context) {
res := models.LicenseResponse{
Data: []models.LicenseDB{license},
Status: http.StatusOK,
Meta: models.Meta{
Meta: models.PaginationMeta{
ResourceCount: 1,
},
}
Expand Down Expand Up @@ -105,7 +129,7 @@ func CreateLicense(c *gin.Context) {
}
license := models.LicenseDB(input)

result := DB.FirstOrCreate(&license)
result := db.DB.FirstOrCreate(&license)
if result.RowsAffected == 0 {

er := models.LicenseError{
Expand All @@ -132,7 +156,7 @@ func CreateLicense(c *gin.Context) {
res := models.LicenseResponse{
Data: []models.LicenseDB{license},
Status: http.StatusCreated,
Meta: models.Meta{
Meta: models.PaginationMeta{
ResourceCount: 1,
},
}
Expand All @@ -144,7 +168,7 @@ func UpdateLicense(c *gin.Context) {
var update models.LicenseDB
var license models.LicenseDB
shortname := c.Param("shortname")
if err := DB.Where("shortname = ?", shortname).First(&license).Error; err != nil {
if err := db.DB.Where("shortname = ?", shortname).First(&license).Error; err != nil {
er := models.LicenseError{
Status: http.StatusBadRequest,
Message: fmt.Sprintf("license with shortname '%s' not found", shortname),
Expand All @@ -166,7 +190,7 @@ func UpdateLicense(c *gin.Context) {
c.JSON(http.StatusBadRequest, er)
return
}
if err := DB.Model(&license).Updates(update).Error; err != nil {
if err := db.DB.Model(&license).Updates(update).Error; err != nil {
er := models.LicenseError{
Status: http.StatusInternalServerError,
Message: "Failed to update license",
Expand All @@ -180,7 +204,7 @@ func UpdateLicense(c *gin.Context) {
res := models.LicenseResponse{
Data: []models.LicenseDB{license},
Status: http.StatusOK,
Meta: models.Meta{
Meta: models.PaginationMeta{
ResourceCount: 1,
},
}
Expand All @@ -193,16 +217,62 @@ func SearchInLicense(c *gin.Context) {
field := c.Query("field")
search_term := c.Query("search_term")
search := c.Query("search")
if field == "" && search_term == "" {
SpdxId := c.Query("spdxid")
DetectorType := c.Query("detector_type")
GPLv2compatible := c.Query("gplv2compatible")
GPLv3compatible := c.Query("gplv3compatible")
marydone := c.Query("marydone")
active := c.Query("active")
OSIapproved := c.Query("osiapproved")
fsffree := c.Query("fsffree")
copyleft := c.Query("copyleft")
var license []models.LicenseDB
query := db.DB.Model(&license)

if field == "" && search_term == "" && SpdxId == "" && GPLv2compatible == "" && GPLv3compatible == "" && DetectorType == "" && marydone == "" && active == "" && fsffree == "" && OSIapproved == "" && copyleft == "" {
GetAllLicense(c)
return
}
var query *gorm.DB
var license []models.LicenseDB
if active != "" {
query = query.Where("active=?", active)
}

if fsffree != "" {
query = query.Where("fs_ffree=?", fsffree)
}

if OSIapproved != "" {
query = query.Where("os_iapproved=?", OSIapproved)
}

if copyleft != "" {
query = query.Where("copyleft=?", copyleft)
}

if SpdxId != "" {
query = query.Where("spdx_id=?", SpdxId)
}

if DetectorType != "" {
query = query.Where("detector_type=?", DetectorType)
}

if GPLv2compatible != "" {
query = query.Where("gp_lv2compatible=?", GPLv2compatible)
}

if GPLv3compatible != "" {
query = query.Where("gp_lv3compatible=?", GPLv3compatible)
}

if marydone != "" {
query = query.Where("marydone=?", marydone)
}

if search == "fuzzy" {
query = DB.Where(fmt.Sprintf("%s ILIKE ?", field), fmt.Sprintf("%%%s%%", search_term)).Find(&license)
query = query.Where(fmt.Sprintf("%s ILIKE ?", field), fmt.Sprintf("%%%s%%", search_term))
} else if search == "" || search == "full_text_search" {
query = DB.Where(field+" @@ plainto_tsquery(?)", search_term).Find(&license)
query = query.Where(field+" @@ plainto_tsquery(?)", search_term)
} else {
er := models.LicenseError{
Status: http.StatusBadRequest,
Expand All @@ -226,10 +296,12 @@ func SearchInLicense(c *gin.Context) {
c.JSON(http.StatusBadRequest, er)
return
}
query.Find(&license)

res := models.LicenseResponse{
Data: license,
Status: http.StatusOK,
Meta: models.Meta{
Meta: models.PaginationMeta{
ResourceCount: len(license),
},
}
Expand Down
Loading

0 comments on commit 721d8f1

Please sign in to comment.