@@ -3,33 +3,45 @@ use crate::{
3
3
license:: model:: {
4
4
SpdxLicenseDetails , SpdxLicenseSummary ,
5
5
sbom_license:: {
6
- ExtractedLicensingInfos , Purl , SbomNameId , SbomPackageLicense , SbomPackageLicenseBase ,
6
+ ExtractedLicensingInfos , MergedSbomPackageLicense , Purl , SbomNameId ,
7
+ SbomPackageLicense , SbomPackageLicenseBase ,
7
8
} ,
8
9
} ,
9
10
} ;
10
11
use sea_orm:: { ColumnTrait , ConnectionTrait , EntityTrait , QueryFilter , QuerySelect , RelationTrait } ;
11
12
use sea_query:: { Condition , JoinType } ;
13
+ use std:: collections:: HashMap ;
12
14
use trustify_common:: {
13
15
db:: query:: Query ,
14
16
id:: { Id , TrySelectForId } ,
15
17
model:: { Paginated , PaginatedResults } ,
16
18
} ;
17
19
use trustify_entity:: {
18
20
license, licensing_infos, qualified_purl, sbom, sbom_node, sbom_package, sbom_package_cpe_ref,
19
- sbom_package_license:: { self , LicenseCategory } ,
20
- sbom_package_purl_ref,
21
+ sbom_package_license, sbom_package_purl_ref,
21
22
} ;
23
+ use uuid:: Uuid ;
22
24
23
25
pub mod license_export;
24
26
25
27
pub struct LicenseService { }
26
28
29
+ #[ derive( Debug , Clone ) ]
27
30
pub struct LicenseExportResult {
28
31
pub sbom_package_license : Vec < SbomPackageLicense > ,
29
32
pub extracted_licensing_infos : Vec < ExtractedLicensingInfos > ,
30
33
pub sbom_name_group_version : Option < SbomNameId > ,
31
34
}
32
35
36
+ #[ derive( Eq , Hash , PartialEq ) ]
37
+ pub struct SbomPackageLicenseBasekey {
38
+ pub node_id : String ,
39
+ pub sbom_id : Uuid ,
40
+ pub name : String ,
41
+ pub group : Option < String > ,
42
+ pub version : Option < String > ,
43
+ }
44
+
33
45
impl Default for LicenseService {
34
46
fn default ( ) -> Self {
35
47
Self :: new ( )
@@ -46,12 +58,13 @@ impl LicenseService {
46
58
id : Id ,
47
59
connection : & C ,
48
60
) -> Result < LicenseExportResult , Error > {
49
- let name_version_group = sbom:: Entity :: find ( )
61
+ let name_version_group: Option < SbomNameId > = sbom:: Entity :: find ( )
50
62
. try_filter ( id. clone ( ) ) ?
51
63
. join ( JoinType :: Join , sbom:: Relation :: SbomNode . def ( ) )
52
64
. select_only ( )
53
65
. column_as ( sbom:: Column :: DocumentId , "sbom_id" )
54
66
. column_as ( sbom_node:: Column :: Name , "sbom_name" )
67
+ . column_as ( sbom:: Column :: Labels , "labels" )
55
68
. into_model :: < SbomNameId > ( )
56
69
. one ( connection)
57
70
. await ?;
@@ -68,23 +81,78 @@ impl LicenseService {
68
81
JoinType :: InnerJoin ,
69
82
sbom_package_license:: Relation :: License . def ( ) ,
70
83
)
71
- . filter (
72
- Condition :: all ( )
73
- . add ( sbom_package_license:: Column :: LicenseType . eq ( LicenseCategory :: Declared ) ) ,
74
- )
75
84
. select_only ( )
76
85
. column_as ( sbom:: Column :: SbomId , "sbom_id" )
77
86
. column_as ( sbom_package:: Column :: NodeId , "node_id" )
78
87
. column_as ( sbom_node:: Column :: Name , "name" )
79
88
. column_as ( sbom_package:: Column :: Group , "group" )
80
89
. column_as ( sbom_package:: Column :: Version , "version" )
81
90
. column_as ( license:: Column :: Text , "license_text" )
91
+ . column_as ( sbom_package_license:: Column :: LicenseType , "license_type" )
82
92
. into_model :: < SbomPackageLicenseBase > ( )
83
93
. all ( connection)
84
94
. await ?;
85
95
96
+ fn merge_package_licenses_for_spdx (
97
+ package_licenses : Vec < SbomPackageLicenseBase > ,
98
+ ) -> Vec < MergedSbomPackageLicense > {
99
+ let mut grouped: HashMap < SbomPackageLicenseBasekey , MergedSbomPackageLicense > =
100
+ HashMap :: new ( ) ;
101
+
102
+ for license in package_licenses {
103
+ let key = SbomPackageLicenseBasekey {
104
+ node_id : license. node_id . clone ( ) ,
105
+ sbom_id : license. sbom_id ,
106
+ name : license. name . clone ( ) ,
107
+ group : license. group . clone ( ) ,
108
+ version : license. version . clone ( ) ,
109
+ } ;
110
+
111
+ grouped
112
+ . entry ( key)
113
+ . or_insert_with ( || MergedSbomPackageLicense {
114
+ node_id : license. node_id . clone ( ) ,
115
+ sbom_id : license. sbom_id ,
116
+ name : license. name . clone ( ) ,
117
+ group : license. group . clone ( ) ,
118
+ version : license. version . clone ( ) ,
119
+ license_declared_text : None ,
120
+ license_concluded_text : None ,
121
+ } )
122
+ . apply_license ( & license) ;
123
+ }
124
+ grouped. into_values ( ) . collect ( )
125
+ }
126
+
127
+ fn merge_package_licenses_for_cydx (
128
+ package_licenses : Vec < SbomPackageLicenseBase > ,
129
+ ) -> Vec < MergedSbomPackageLicense > {
130
+ package_licenses
131
+ . into_iter ( )
132
+ . map ( |cydx| MergedSbomPackageLicense {
133
+ node_id : cydx. node_id ,
134
+ sbom_id : cydx. sbom_id ,
135
+ name : cydx. name ,
136
+ group : cydx. group ,
137
+ version : cydx. version ,
138
+ license_declared_text : cydx. license_text ,
139
+ license_concluded_text : None ,
140
+ } )
141
+ . collect ( )
142
+ }
143
+
144
+ let package_license_list = if let Some ( nvg) = name_version_group. clone ( ) {
145
+ if nvg. labels . 0 . get ( "type" ) . map ( String :: as_str) == Some ( "spdx" ) {
146
+ merge_package_licenses_for_spdx ( package_license)
147
+ } else {
148
+ merge_package_licenses_for_cydx ( package_license)
149
+ }
150
+ } else {
151
+ merge_package_licenses_for_cydx ( package_license)
152
+ } ;
153
+
86
154
let mut sbom_package_list = Vec :: new ( ) ;
87
- for spl in package_license {
155
+ for spl in package_license_list {
88
156
let result_purl: Vec < Purl > = sbom_package_purl_ref:: Entity :: find ( )
89
157
. join ( JoinType :: Join , sbom_package_purl_ref:: Relation :: Purl . def ( ) )
90
158
. filter (
@@ -123,7 +191,8 @@ impl LicenseService {
123
191
version : spl. version ,
124
192
purl : result_purl,
125
193
cpe : result_cpe,
126
- license_text : spl. license_text ,
194
+ license_declared_text : spl. license_declared_text ,
195
+ license_concluded_text : spl. license_concluded_text ,
127
196
} ) ;
128
197
}
129
198
let license_info_list: Vec < ExtractedLicensingInfos > = licensing_infos:: Entity :: find ( )
0 commit comments