Skip to content

Commit 9e01c84

Browse files
committed
feat(externalref): Add external ref to obligations
Signed-off-by: deo002 <[email protected]>
1 parent 3169bfa commit 9e01c84

File tree

9 files changed

+225
-54
lines changed

9 files changed

+225
-54
lines changed

cmd/laas/docs/docs.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2475,6 +2475,9 @@ const docTemplate = `{
24752475
"datatypes.JSONType-models_LicenseDBSchemaExtension": {
24762476
"type": "object"
24772477
},
2478+
"datatypes.JSONType-models_ObligationSchemaExtension": {
2479+
"type": "object"
2480+
},
24782481
"models.APICollection": {
24792482
"type": "object",
24802483
"properties": {
@@ -3089,6 +3092,9 @@ const docTemplate = `{
30893092
"comment": {
30903093
"type": "string"
30913094
},
3095+
"externalRef": {
3096+
"$ref": "#/definitions/datatypes.JSONType-models_ObligationSchemaExtension"
3097+
},
30923098
"id": {
30933099
"type": "integer"
30943100
},
@@ -3184,6 +3190,9 @@ const docTemplate = `{
31843190
"comment": {
31853191
"type": "string"
31863192
},
3193+
"external_ref": {
3194+
"$ref": "#/definitions/models.ObligationSchemaExtension"
3195+
},
31873196
"modifications": {
31883197
"type": "boolean",
31893198
"example": true
@@ -3324,6 +3333,17 @@ const docTemplate = `{
33243333
}
33253334
}
33263335
},
3336+
"models.ObligationSchemaExtension": {
3337+
"type": "object",
3338+
"properties": {
3339+
"obligation_explanation": {
3340+
"type": "string"
3341+
},
3342+
"obligation_suffix": {
3343+
"type": "string"
3344+
}
3345+
}
3346+
},
33273347
"models.ObligationType": {
33283348
"type": "object",
33293349
"required": [
@@ -3371,6 +3391,10 @@ const docTemplate = `{
33713391
"comment": {
33723392
"type": "string"
33733393
},
3394+
"external_ref": {
3395+
"type": "object",
3396+
"additionalProperties": true
3397+
},
33743398
"modifications": {
33753399
"type": "boolean",
33763400
"example": true

cmd/laas/docs/swagger.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2468,6 +2468,9 @@
24682468
"datatypes.JSONType-models_LicenseDBSchemaExtension": {
24692469
"type": "object"
24702470
},
2471+
"datatypes.JSONType-models_ObligationSchemaExtension": {
2472+
"type": "object"
2473+
},
24712474
"models.APICollection": {
24722475
"type": "object",
24732476
"properties": {
@@ -3082,6 +3085,9 @@
30823085
"comment": {
30833086
"type": "string"
30843087
},
3088+
"externalRef": {
3089+
"$ref": "#/definitions/datatypes.JSONType-models_ObligationSchemaExtension"
3090+
},
30853091
"id": {
30863092
"type": "integer"
30873093
},
@@ -3177,6 +3183,9 @@
31773183
"comment": {
31783184
"type": "string"
31793185
},
3186+
"external_ref": {
3187+
"$ref": "#/definitions/models.ObligationSchemaExtension"
3188+
},
31803189
"modifications": {
31813190
"type": "boolean",
31823191
"example": true
@@ -3317,6 +3326,17 @@
33173326
}
33183327
}
33193328
},
3329+
"models.ObligationSchemaExtension": {
3330+
"type": "object",
3331+
"properties": {
3332+
"obligation_explanation": {
3333+
"type": "string"
3334+
},
3335+
"obligation_suffix": {
3336+
"type": "string"
3337+
}
3338+
}
3339+
},
33203340
"models.ObligationType": {
33213341
"type": "object",
33223342
"required": [
@@ -3364,6 +3384,10 @@
33643384
"comment": {
33653385
"type": "string"
33663386
},
3387+
"external_ref": {
3388+
"type": "object",
3389+
"additionalProperties": true
3390+
},
33673391
"modifications": {
33683392
"type": "boolean",
33693393
"example": true

cmd/laas/docs/swagger.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ basePath: /api/v1
22
definitions:
33
datatypes.JSONType-models_LicenseDBSchemaExtension:
44
type: object
5+
datatypes.JSONType-models_ObligationSchemaExtension:
6+
type: object
57
models.APICollection:
68
properties:
79
authenticated:
@@ -431,6 +433,8 @@ definitions:
431433
$ref: '#/definitions/models.ObligationClassification'
432434
comment:
433435
type: string
436+
externalRef:
437+
$ref: '#/definitions/datatypes.JSONType-models_ObligationSchemaExtension'
434438
id:
435439
type: integer
436440
licenses:
@@ -490,6 +494,8 @@ definitions:
490494
type: string
491495
comment:
492496
type: string
497+
external_ref:
498+
$ref: '#/definitions/models.ObligationSchemaExtension'
493499
modifications:
494500
example: true
495501
type: boolean
@@ -595,6 +601,13 @@ definitions:
595601
example: 200
596602
type: integer
597603
type: object
604+
models.ObligationSchemaExtension:
605+
properties:
606+
obligation_explanation:
607+
type: string
608+
obligation_suffix:
609+
type: string
610+
type: object
598611
models.ObligationType:
599612
properties:
600613
type:
@@ -627,6 +640,9 @@ definitions:
627640
type: string
628641
comment:
629642
type: string
643+
external_ref:
644+
additionalProperties: true
645+
type: object
630646
modifications:
631647
example: true
632648
type: boolean

cmd/laas/gen_external_ref_schema.go

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,20 @@ type ExternalRefFields struct {
3636
Fields []ExternalRefFieldMetaData `yaml:"fields"`
3737
}
3838

39+
type ExternalRefYAML struct {
40+
License ExternalRefFields `yaml:"license"`
41+
Obligation ExternalRefFields `yaml:"obligation"`
42+
}
43+
3944
func main() {
40-
externalRefFields := ExternalRefFields{}
45+
externalRefYAML := ExternalRefYAML{}
4146

4247
fieldsMetadata, err := os.ReadFile(PATH_EXTERNAL_REF_CONFIG_FILE)
4348
if err != nil {
4449
log.Fatalf("Failed to instantiate json schema for external ref in license: %v", err)
4550
}
4651

47-
err = yaml.Unmarshal(fieldsMetadata, &externalRefFields)
52+
err = yaml.Unmarshal(fieldsMetadata, &externalRefYAML)
4853
if err != nil {
4954
log.Fatalf("Failed to instantiate json schema for external ref in license: %v", err)
5055
}
@@ -56,9 +61,34 @@ func main() {
5661

5762
// REUSE-IgnoreStart
5863

59-
var fields []jen.Code
64+
var licenseFields, obligationFields []jen.Code
65+
66+
for _, f := range externalRefYAML.License.Fields {
67+
field := jen.Id(f.StructFieldName).Op("*")
68+
if f.StructFieldName == "" {
69+
err = errors.New("field struct_field_name is missing in external_ref_fields.yaml")
70+
}
71+
switch f.Type {
72+
case "boolean":
73+
field = field.Bool()
74+
case "string":
75+
field = field.String()
76+
case "int":
77+
field = field.Int64()
78+
default:
79+
err = fmt.Errorf("type %s in external_ref_fields.yaml is not supported", f.Type)
80+
}
81+
if err != nil {
82+
log.Fatalf("Failed to instantiate json schema for external ref in license: %v", err)
83+
return
84+
}
85+
field = field.Tag(map[string]string{"json": fmt.Sprintf("%s,omitempty", f.Name)})
86+
licenseFields = append(licenseFields, field)
87+
}
88+
89+
f.Type().Id("LicenseDBSchemaExtension").Struct(licenseFields...)
6090

61-
for _, f := range externalRefFields.Fields {
91+
for _, f := range externalRefYAML.Obligation.Fields {
6292
field := jen.Id(f.StructFieldName).Op("*")
6393
if f.StructFieldName == "" {
6494
err = errors.New("field struct_field_name is missing in external_ref_fields.yaml")
@@ -77,11 +107,11 @@ func main() {
77107
log.Fatalf("Failed to instantiate json schema for external ref in license: %v", err)
78108
return
79109
}
80-
field = field.Tag(map[string]string{"json": fmt.Sprintf("%s,omitempty", f.Name), "swaggerignore": "true"})
81-
fields = append(fields, field)
110+
field = field.Tag(map[string]string{"json": fmt.Sprintf("%s,omitempty", f.Name)})
111+
obligationFields = append(obligationFields, field)
82112
}
83113

84-
f.Type().Id("LicenseDBSchemaExtension").Struct(fields...)
114+
f.Type().Id("ObligationSchemaExtension").Struct(obligationFields...)
85115
f.Save(PATH_EXTERNAL_REF_STRUCT_FILE)
86116

87117
}

external_ref_fields.example.yaml

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,32 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
# SPDX-FileCopyrightText: FOSSology contributors
33

4-
fields:
5-
- name: "license_suffix"
6-
type: "string"
7-
struct_field_name: "LicenseSuffix"
8-
label: "License Suffix"
9-
formComponentPath: "../components/dynamic/inputField"
10-
componentType: "input"
11-
- name: "license_explanation"
12-
type: "string"
13-
struct_field_name: "LicenseExplanation"
14-
label: "License Explanation"
15-
formComponentPath: "../components/dynamic/inputField"
16-
componentType: "input"
4+
license:
5+
fields:
6+
- name: "license_suffix"
7+
type: "string"
8+
struct_field_name: "LicenseSuffix"
9+
label: "License Suffix"
10+
formComponentPath: "../components/dynamic/inputField"
11+
componentType: "input"
12+
- name: "license_explanation"
13+
type: "string"
14+
struct_field_name: "LicenseExplanation"
15+
label: "License Explanation"
16+
formComponentPath: "../components/dynamic/inputField"
17+
componentType: "input"
18+
19+
obligation:
20+
fields:
21+
- name: "obligation_suffix"
22+
type: "string"
23+
struct_field_name: "ObligationSuffix"
24+
label: "Obligation Suffix"
25+
formComponentPath: "../components/dynamic/inputField"
26+
componentType: "input"
27+
- name: "obligation_explanation"
28+
type: "string"
29+
struct_field_name: "ObligationExplanation"
30+
label: "Obligation Explanation"
31+
formComponentPath: "../components/dynamic/inputField"
32+
componentType: "input"

pkg/api/obligations.go

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"fmt"
1616
"net/http"
1717
"path/filepath"
18+
"reflect"
1819
"strconv"
1920
"strings"
2021
"time"
@@ -280,7 +281,21 @@ func UpdateObligation(c *gin.Context) {
280281
if err := db.DB.Transaction(func(tx *gorm.DB) error {
281282
// https://gorm.io/docs/context.html#Context-in-Hooks-x2F-Callbacks
282283
ctx := context.WithValue(context.Background(), models.ContextKey("oldObligation"), &oldObligation)
283-
if err := tx.WithContext(ctx).Omit("Licenses", "Topic").Updates(&newObligation).Error; err != nil {
284+
285+
if err := tx.WithContext(ctx).Omit("Licenses", "Topic", "ExternalRef").Updates(&newObligation).Error; err != nil {
286+
return err
287+
}
288+
289+
// Overwrite values of existing keys, add new key value pairs and remove keys with null values.
290+
if err := tx.Debug().Model(&models.Obligation{}).Where(&models.Obligation{Id: newObligation.Id}).UpdateColumn("external_ref", gorm.Expr("jsonb_strip_nulls(COALESCE(external_ref, '{}'::jsonb) || ?)", updates.ExternalRef)).Error; err != nil {
291+
er := models.LicenseError{
292+
Status: http.StatusInternalServerError,
293+
Message: "Failed to update license",
294+
Error: err.Error(),
295+
Path: c.Request.URL.Path,
296+
Timestamp: time.Now().Format(time.RFC3339),
297+
}
298+
c.JSON(http.StatusInternalServerError, er)
284299
return err
285300
}
286301

@@ -683,6 +698,32 @@ func addChangelogsForObligation(tx *gorm.DB, userId int64,
683698

684699
utils.AddChangelog("Text Updatable", oldObligation.TextUpdatable, newObligation.TextUpdatable, &changes)
685700

701+
oldLicenseExternalRef := oldObligation.ExternalRef.Data()
702+
oldExternalRefVal := reflect.ValueOf(oldLicenseExternalRef)
703+
typesOf := oldExternalRefVal.Type()
704+
705+
newLicenseExternalRef := newObligation.ExternalRef.Data()
706+
newExternalRefVal := reflect.ValueOf(newLicenseExternalRef)
707+
708+
for i := 0; i < oldExternalRefVal.NumField(); i++ {
709+
fieldName := typesOf.Field(i).Name
710+
711+
switch typesOf.Field(i).Type.String() {
712+
case "*boolean":
713+
oldFieldPtr, _ := oldExternalRefVal.Field(i).Interface().(*bool)
714+
newFieldPtr, _ := newExternalRefVal.Field(i).Interface().(*bool)
715+
utils.AddChangelog(fmt.Sprintf("External Reference %s", fieldName), oldFieldPtr, newFieldPtr, &changes)
716+
case "*string":
717+
oldFieldPtr, _ := oldExternalRefVal.Field(i).Interface().(*string)
718+
newFieldPtr, _ := newExternalRefVal.Field(i).Interface().(*string)
719+
utils.AddChangelog(fmt.Sprintf("External Reference %s", fieldName), oldFieldPtr, newFieldPtr, &changes)
720+
case "*int":
721+
oldFieldPtr, _ := oldExternalRefVal.Field(i).Interface().(*int)
722+
newFieldPtr, _ := newExternalRefVal.Field(i).Interface().(*int)
723+
utils.AddChangelog(fmt.Sprintf("External Reference %s", fieldName), oldFieldPtr, newFieldPtr, &changes)
724+
}
725+
}
726+
686727
if len(changes) != 0 {
687728
audit := models.Audit{
688729
UserId: userId,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- SPDX-FileCopyrightText: 2025 Siemens AG
2+
-- SPDX-FileCopyrightText: 2025 Dearsh Oberoi <[email protected]>
3+
-- SPDX-License-Identifier: GPL-2.0-only
4+
5+
ALTER TABLE obligations DROP external_ref;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- SPDX-FileCopyrightText: 2025 Siemens AG
2+
-- SPDX-FileCopyrightText: 2025 Dearsh Oberoi <[email protected]>
3+
-- SPDX-License-Identifier: GPL-2.0-only
4+
5+
ALTER TABLE obligations ADD external_ref JSONB;

0 commit comments

Comments
 (0)