diff --git a/cmd/laas/docs/docs.go b/cmd/laas/docs/docs.go index c3d2aee..34189d0 100644 --- a/cmd/laas/docs/docs.go +++ b/cmd/laas/docs/docs.go @@ -683,75 +683,6 @@ const docTemplate = `{ } } } - }, - "patch": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Update a license in the service", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Licenses" - ], - "summary": "Update a license", - "operationId": "UpdateLicense", - "parameters": [ - { - "type": "string", - "description": "Shortname of the license to be updated", - "name": "shortname", - "in": "path", - "required": true - }, - { - "description": "Update license body (requires only the fields to be updated)", - "name": "license", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/models.LicenseUpdateJSONSchema" - } - } - ], - "responses": { - "200": { - "description": "License updated successfully", - "schema": { - "$ref": "#/definitions/models.LicenseResponse" - } - }, - "400": { - "description": "Invalid license body", - "schema": { - "$ref": "#/definitions/models.LicenseError" - } - }, - "404": { - "description": "License with shortname not found", - "schema": { - "$ref": "#/definitions/models.LicenseError" - } - }, - "409": { - "description": "License with same shortname already exists", - "schema": { - "$ref": "#/definitions/models.LicenseError" - } - }, - "500": { - "description": "Failed to update license", - "schema": { - "$ref": "#/definitions/models.LicenseError" - } - } - } } }, "/login": { @@ -1926,6 +1857,14 @@ const docTemplate = `{ "url": { "type": "string", "example": "https://opensource.org/licenses/MIT" + }, + "user": { + "description": "Reference to User", + "allOf": [ + { + "$ref": "#/definitions/models.User" + } + ] } } }, @@ -2055,98 +1994,6 @@ const docTemplate = `{ } } }, - "models.LicenseUpdateJSONSchema": { - "type": "object", - "properties": { - "FSFfree": { - "type": "boolean", - "example": false - }, - "Fedora": { - "type": "string", - "example": "Fedora" - }, - "GPLv2compatible": { - "type": "boolean", - "example": false - }, - "GPLv3compatible": { - "type": "boolean", - "example": false - }, - "OSIapproved": { - "type": "boolean", - "example": false - }, - "active": { - "type": "boolean", - "example": true - }, - "copyleft": { - "type": "boolean", - "example": false - }, - "detector_type": { - "type": "integer", - "maximum": 2, - "minimum": 0, - "example": 1 - }, - "external_ref": { - "$ref": "#/definitions/datatypes.JSONType-models_LicenseDBSchemaExtension" - }, - "flag": { - "type": "integer", - "maximum": 2, - "minimum": 0, - "example": 1 - }, - "fullname": { - "type": "string", - "example": "MIT License" - }, - "marydone": { - "type": "boolean", - "example": false - }, - "notes": { - "type": "string", - "example": "This license has been superseded." - }, - "obligations": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Obligation" - } - }, - "risk": { - "type": "integer", - "maximum": 5, - "minimum": 0, - "example": 1 - }, - "source": { - "type": "string", - "example": "Source" - }, - "spdx_id": { - "type": "string", - "example": "MIT" - }, - "text": { - "type": "string", - "example": "MIT License Text here" - }, - "text_updatable": { - "type": "boolean", - "example": false - }, - "url": { - "type": "string", - "example": "https://opensource.org/licenses/MIT" - } - } - }, "models.Obligation": { "type": "object", "properties": { diff --git a/cmd/laas/docs/swagger.json b/cmd/laas/docs/swagger.json index 3e251d7..678e917 100644 --- a/cmd/laas/docs/swagger.json +++ b/cmd/laas/docs/swagger.json @@ -676,75 +676,6 @@ } } } - }, - "patch": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Update a license in the service", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Licenses" - ], - "summary": "Update a license", - "operationId": "UpdateLicense", - "parameters": [ - { - "type": "string", - "description": "Shortname of the license to be updated", - "name": "shortname", - "in": "path", - "required": true - }, - { - "description": "Update license body (requires only the fields to be updated)", - "name": "license", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/models.LicenseUpdateJSONSchema" - } - } - ], - "responses": { - "200": { - "description": "License updated successfully", - "schema": { - "$ref": "#/definitions/models.LicenseResponse" - } - }, - "400": { - "description": "Invalid license body", - "schema": { - "$ref": "#/definitions/models.LicenseError" - } - }, - "404": { - "description": "License with shortname not found", - "schema": { - "$ref": "#/definitions/models.LicenseError" - } - }, - "409": { - "description": "License with same shortname already exists", - "schema": { - "$ref": "#/definitions/models.LicenseError" - } - }, - "500": { - "description": "Failed to update license", - "schema": { - "$ref": "#/definitions/models.LicenseError" - } - } - } } }, "/login": { @@ -1919,6 +1850,14 @@ "url": { "type": "string", "example": "https://opensource.org/licenses/MIT" + }, + "user": { + "description": "Reference to User", + "allOf": [ + { + "$ref": "#/definitions/models.User" + } + ] } } }, @@ -2048,98 +1987,6 @@ } } }, - "models.LicenseUpdateJSONSchema": { - "type": "object", - "properties": { - "FSFfree": { - "type": "boolean", - "example": false - }, - "Fedora": { - "type": "string", - "example": "Fedora" - }, - "GPLv2compatible": { - "type": "boolean", - "example": false - }, - "GPLv3compatible": { - "type": "boolean", - "example": false - }, - "OSIapproved": { - "type": "boolean", - "example": false - }, - "active": { - "type": "boolean", - "example": true - }, - "copyleft": { - "type": "boolean", - "example": false - }, - "detector_type": { - "type": "integer", - "maximum": 2, - "minimum": 0, - "example": 1 - }, - "external_ref": { - "$ref": "#/definitions/datatypes.JSONType-models_LicenseDBSchemaExtension" - }, - "flag": { - "type": "integer", - "maximum": 2, - "minimum": 0, - "example": 1 - }, - "fullname": { - "type": "string", - "example": "MIT License" - }, - "marydone": { - "type": "boolean", - "example": false - }, - "notes": { - "type": "string", - "example": "This license has been superseded." - }, - "obligations": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Obligation" - } - }, - "risk": { - "type": "integer", - "maximum": 5, - "minimum": 0, - "example": 1 - }, - "source": { - "type": "string", - "example": "Source" - }, - "spdx_id": { - "type": "string", - "example": "MIT" - }, - "text": { - "type": "string", - "example": "MIT License Text here" - }, - "text_updatable": { - "type": "boolean", - "example": false - }, - "url": { - "type": "string", - "example": "https://opensource.org/licenses/MIT" - } - } - }, "models.Obligation": { "type": "object", "properties": { diff --git a/cmd/laas/docs/swagger.yaml b/cmd/laas/docs/swagger.yaml index 38ae564..77cbdf7 100644 --- a/cmd/laas/docs/swagger.yaml +++ b/cmd/laas/docs/swagger.yaml @@ -167,6 +167,10 @@ definitions: url: example: https://opensource.org/licenses/MIT type: string + user: + allOf: + - $ref: '#/definitions/models.User' + description: Reference to User required: - fullname - shortname @@ -259,75 +263,6 @@ definitions: type: string type: array type: object - models.LicenseUpdateJSONSchema: - properties: - FSFfree: - example: false - type: boolean - Fedora: - example: Fedora - type: string - GPLv2compatible: - example: false - type: boolean - GPLv3compatible: - example: false - type: boolean - OSIapproved: - example: false - type: boolean - active: - example: true - type: boolean - copyleft: - example: false - type: boolean - detector_type: - example: 1 - maximum: 2 - minimum: 0 - type: integer - external_ref: - $ref: '#/definitions/datatypes.JSONType-models_LicenseDBSchemaExtension' - flag: - example: 1 - maximum: 2 - minimum: 0 - type: integer - fullname: - example: MIT License - type: string - marydone: - example: false - type: boolean - notes: - example: This license has been superseded. - type: string - obligations: - items: - $ref: '#/definitions/models.Obligation' - type: array - risk: - example: 1 - maximum: 5 - minimum: 0 - type: integer - source: - example: Source - type: string - spdx_id: - example: MIT - type: string - text: - example: MIT License Text here - type: string - text_updatable: - example: false - type: boolean - url: - example: https://opensource.org/licenses/MIT - type: string - type: object models.Obligation: properties: active: @@ -962,51 +897,6 @@ paths: summary: Get a license by shortname tags: - Licenses - patch: - consumes: - - application/json - description: Update a license in the service - operationId: UpdateLicense - parameters: - - description: Shortname of the license to be updated - in: path - name: shortname - required: true - type: string - - description: Update license body (requires only the fields to be updated) - in: body - name: license - required: true - schema: - $ref: '#/definitions/models.LicenseUpdateJSONSchema' - produces: - - application/json - responses: - "200": - description: License updated successfully - schema: - $ref: '#/definitions/models.LicenseResponse' - "400": - description: Invalid license body - schema: - $ref: '#/definitions/models.LicenseError' - "404": - description: License with shortname not found - schema: - $ref: '#/definitions/models.LicenseError' - "409": - description: License with same shortname already exists - schema: - $ref: '#/definitions/models.LicenseError' - "500": - description: Failed to update license - schema: - $ref: '#/definitions/models.LicenseError' - security: - - ApiKeyAuth: [] - summary: Update a license - tags: - - Licenses /licenses/export: get: description: Export all licenses as a json file diff --git a/pkg/api/licenses.go b/pkg/api/licenses.go index 8260528..68ef445 100644 --- a/pkg/api/licenses.go +++ b/pkg/api/licenses.go @@ -7,6 +7,7 @@ package api import ( + "context" "encoding/json" "errors" "fmt" @@ -85,7 +86,7 @@ func FilterLicense(c *gin.Context) { } var licenses []models.LicenseDB - query := db.DB.Model(&licenses) + query := db.DB.Model(&licenses).Preload("User") if active != "" { parsedActive, err := strconv.ParseBool(active) @@ -295,9 +296,13 @@ func CreateLicense(c *gin.Context) { return } - result := db.DB. + username := c.GetString("username") + ctx := context.WithValue(context.Background(), models.ContextKey("user"), username) + + result := db.DB.WithContext(ctx). Where(&models.LicenseDB{Shortname: input.Shortname}). FirstOrCreate(&input) + if result.Error != nil { er := models.LicenseError{ Status: http.StatusInternalServerError, @@ -348,6 +353,8 @@ func CreateLicense(c *gin.Context) { // @Failure 500 {object} models.LicenseError "Failed to update license" // @Security ApiKeyAuth // @Router /licenses/{shortname} [patch] +type ContextKey string + func UpdateLicense(c *gin.Context) { _ = db.DB.Transaction(func(tx *gorm.DB) error { var updates models.LicenseUpdateJSONSchema diff --git a/pkg/models/types.go b/pkg/models/types.go index 0b03331..936f7dd 100644 --- a/pkg/models/types.go +++ b/pkg/models/types.go @@ -47,9 +47,39 @@ type LicenseDB struct { Marydone *bool `json:"marydone" gorm:"column:marydone;not null;default:false"` ExternalRef datatypes.JSONType[LicenseDBSchemaExtension] `json:"external_ref"` Obligations []*Obligation `gorm:"many2many:obligation_licenses;" json:"obligations"` + UserId int64 `json:"-" example:"123"` // Foreign key to User + User User `gorm:"foreignKey:UserId;references:Id" json:"user"` // Reference to User } -func (l *LicenseDB) BeforeSave(tx *gorm.DB) (err error) { +// BeforeCreate hook to validate data and log the user who is creating the record +func (l *LicenseDB) BeforeCreate(tx *gorm.DB) (err error) { + username, ok := tx.Statement.Context.Value(ContextKey("user")).(string) + if !ok { + return errors.New("username not found in context") + } + + var user User + if err := tx.Where("username = ?", username).First(&user).Error; err != nil { + return errors.New("user not found") + } + l.UserId = user.Id + + if err := validateLicenseFields(l); err != nil { + return err + } + return nil +} + +// BeforeUpdate hook to validate data and log the user who is updating the record +func (l *LicenseDB) BeforeUpdate(tx *gorm.DB) (err error) { + if err := validateLicenseFields(l); err != nil { + return err + } + return nil +} + +// Helper function to validate fields +func validateLicenseFields(l *LicenseDB) error { if l.Shortname != nil && *l.Shortname == "" { return errors.New("shortname cannot be an empty string") } @@ -62,7 +92,7 @@ func (l *LicenseDB) BeforeSave(tx *gorm.DB) (err error) { if l.SpdxId != nil && *l.SpdxId == "" { return errors.New("spdx_id cannot be an empty string") } - if l.Risk != nil && (*l.Risk < 0 && *l.Risk > 5) { + if l.Risk != nil && (*l.Risk < 0 || *l.Risk > 5) { return errors.New("risk can have values from 0 to 5 only") } if l.Flag != nil && (*l.Flag < 0 || *l.Flag > 2) { @@ -71,7 +101,7 @@ func (l *LicenseDB) BeforeSave(tx *gorm.DB) (err error) { if l.DetectorType != nil && (*l.DetectorType < 0 || *l.DetectorType > 2) { return errors.New("detector_type can have values from 0 to 2 only") } - return + return nil } // LicenseUpdateJSONSchema struct represents the input format for updating an existing license. @@ -99,6 +129,8 @@ type LicenseUpdateJSONSchema struct { Marydone *bool `json:"marydone" example:"false"` ExternalRef datatypes.JSONType[LicenseDBSchemaExtension] `json:"external_ref"` Obligations []*Obligation `json:"obligations"` + UserId int64 `json:"-" example:"123"` // Foreign key to User + User User `json:"-"` // Reference to User } // UpdateExternalRefsJSONPayload struct represents the external ref key value pairs for update @@ -372,7 +404,6 @@ func (o *Obligation) BeforeCreate(tx *gorm.DB) (err error) { type ContextKey string func (o *Obligation) BeforeUpdate(tx *gorm.DB) (err error) { - oldObligation, ok := tx.Statement.Context.Value(ContextKey("oldObligation")).(*Obligation) if !ok { return errors.New("something went wrong") diff --git a/swagger-diff.txt b/swagger-diff.txt new file mode 100644 index 0000000..e69de29