55 "errors"
66 "fmt"
77 "io"
8+ "log/slog"
89 "net/http"
910 "net/url"
1011 "regexp"
@@ -144,6 +145,51 @@ func (u *User) MergeForUpdate(userData []User) error {
144145 return nil
145146}
146147
148+ // Helper function to build service snapshots if compliance policy exists
149+ func (h * Handlers ) buildServiceSnapshots (ctx echo.Context , customizations * Customizations , distribution Distributions ) (* db.ServiceSnapshots , error ) {
150+ if customizations .Openscap == nil {
151+ return nil , nil
152+ }
153+
154+ var compl OpenSCAPCompliance
155+ compl , err := customizations .Openscap .AsOpenSCAPCompliance ()
156+ if err != nil {
157+ slog .ErrorContext (ctx .Request ().Context (), "error in AsOpenSCAPCompliance" , "error" , err .Error ())
158+ return nil , err
159+ }
160+ if compl .PolicyId == uuid .Nil {
161+ return nil , nil
162+ }
163+
164+ var cust Customizations
165+ _ , err = h .lintOpenscap (ctx , & cust , true , distribution , compl .PolicyId .String ())
166+ if err != nil {
167+ slog .ErrorContext (ctx .Request ().Context (), "error getting policy customizations via lintOpenscap" ,
168+ "error" , err .Error (), "distribution" , distribution , "policy_id" , compl .PolicyId .String ())
169+ return nil , err
170+ }
171+
172+ policyCustomizationsJSON , err := json .Marshal (cust )
173+ if err != nil {
174+ slog .ErrorContext (ctx .Request ().Context (), "error marshaling policy customizations to JSON" ,
175+ "error" , err .Error (), "policy_id" , compl .PolicyId .String ())
176+ return nil , err
177+ }
178+
179+ serviceSnapshots := & db.ServiceSnapshots {
180+ Compliance : & db.ComplianceSnapshot {
181+ PolicyId : compl .PolicyId ,
182+ PolicyCustomizations : policyCustomizationsJSON ,
183+ },
184+ }
185+
186+ slog .DebugContext (ctx .Request ().Context (), "built compliance snapshot" ,
187+ "policy_id" , compl .PolicyId ,
188+ "distribution" , distribution )
189+
190+ return serviceSnapshots , nil
191+ }
192+
147193// Util function used to create and update Blueprint from API request (WRITE)
148194func BlueprintFromAPI (cbr CreateBlueprintRequest ) (BlueprintBody , error ) {
149195 bb := BlueprintBody {
@@ -237,7 +283,12 @@ func (h *Handlers) CreateBlueprint(ctx echo.Context) error {
237283
238284 id := uuid .New ()
239285 versionId := uuid .New ()
240- ctx .Logger ().Infof ("Inserting blueprint: %s (%s), for orgID: %s and account: %s" , blueprintRequest .Name , id , userID .OrgID (), userID .AccountNumber ())
286+ slog .DebugContext (ctx .Request ().Context (), "inserting blueprint" ,
287+ "name" , blueprintRequest .Name ,
288+ "id" , id ,
289+ "org_id" , userID .OrgID (),
290+ "account" , userID .AccountNumber ())
291+
241292 desc := ""
242293 if blueprintRequest .Description != nil {
243294 desc = * blueprintRequest .Description
@@ -268,9 +319,26 @@ func (h *Handlers) CreateBlueprint(ctx echo.Context) error {
268319 return err
269320 }
270321
271- err = h .server . db . InsertBlueprint (ctx . Request (). Context (), id , versionId , userID . OrgID (), userID . AccountNumber (), blueprintRequest .Name , desc , body , metadata )
322+ serviceSnapshots , err : = h .buildServiceSnapshots (ctx , & blueprintRequest . Customizations , blueprintRequest .Distribution )
272323 if err != nil {
273- ctx .Logger ().Errorf ("Error inserting id into db: %s" , err .Error ())
324+ slog .ErrorContext (ctx .Request ().Context (), "error building service snapshots" ,
325+ "blueprint_id" , id ,
326+ "error" , err .Error ())
327+ return echo .NewHTTPError (http .StatusInternalServerError , "Failed to build compliance snapshots" )
328+ }
329+
330+ var serviceSnapshotsJSON json.RawMessage
331+ if serviceSnapshots != nil {
332+ serviceSnapshotsJSON , err = json .Marshal (serviceSnapshots )
333+ if err != nil {
334+ return echo .NewHTTPError (http .StatusInternalServerError , "Failed to marshal service snapshots" )
335+ }
336+ }
337+
338+ err = h .server .db .InsertBlueprint (ctx .Request ().Context (), id , versionId , userID .OrgID (), userID .AccountNumber (), blueprintRequest .Name , desc , body , metadata , serviceSnapshotsJSON )
339+ if err != nil {
340+ slog .ErrorContext (ctx .Request ().Context (), "error inserting blueprint with service snapshots into db" ,
341+ "error" , err .Error ())
274342
275343 var e * pgconn.PgError
276344 if errors .As (err , & e ) && e .Code == pgerrcode .UniqueViolation {
@@ -283,7 +351,6 @@ func (h *Handlers) CreateBlueprint(ctx echo.Context) error {
283351 }
284352 return err
285353 }
286- ctx .Logger ().Infof ("Inserted blueprint %s" , id )
287354 return ctx .JSON (http .StatusCreated , ComposeResponse {
288355 Id : id ,
289356 })
@@ -294,8 +361,7 @@ func (h *Handlers) GetBlueprint(ctx echo.Context, id openapi_types.UUID, params
294361 if err != nil {
295362 return err
296363 }
297-
298- ctx .Logger ().Infof ("Fetching blueprint %s" , id )
364+ slog .DebugContext (ctx .Request ().Context (), "fetching blueprint" , "id" , id )
299365 if params .Version != nil && * params .Version <= 0 {
300366 if * params .Version != - 1 {
301367 return echo .NewHTTPError (http .StatusBadRequest , "Invalid version number" )
@@ -366,8 +432,6 @@ func (h *Handlers) ExportBlueprint(ctx echo.Context, id openapi_types.UUID) erro
366432 if err != nil {
367433 return err
368434 }
369-
370- ctx .Logger ().Infof ("Fetching blueprint %s" , id )
371435 blueprintEntry , err := h .server .db .GetBlueprint (ctx .Request ().Context (), id , userID .OrgID (), nil )
372436 if err != nil {
373437 if errors .Is (err , db .ErrBlueprintNotFound ) {
@@ -428,7 +492,7 @@ func (h *Handlers) ExportBlueprint(ctx echo.Context, id openapi_types.UUID) erro
428492 }
429493
430494 if exportedRepositoriesResp .Body == nil {
431- ctx .Logger ().Warnf ( "Unable to export custom repositories, empty body" )
495+ slog . WarnContext ( ctx .Request ().Context (), "unable to export custom repositories, empty body" )
432496 return ctx .JSON (http .StatusOK , blueprintExportResponse )
433497 }
434498
@@ -519,15 +583,32 @@ func (h *Handlers) UpdateBlueprint(ctx echo.Context, blueprintId uuid.UUID) erro
519583 if blueprintRequest .Description != nil {
520584 desc = * blueprintRequest .Description
521585 }
522- err = h .server .db .UpdateBlueprint (ctx .Request ().Context (), versionId , blueprintId , userID .OrgID (), blueprintRequest .Name , desc , body )
586+
587+ serviceSnapshots , err := h .buildServiceSnapshots (ctx , & blueprintRequest .Customizations , blueprintRequest .Distribution )
588+ if err != nil {
589+ slog .ErrorContext (ctx .Request ().Context (), "error building service snapshots" ,
590+ "blueprint_id" , blueprintId ,
591+ "error" , err .Error ())
592+ return echo .NewHTTPError (http .StatusInternalServerError , "Failed to build compliance snapshots" )
593+ }
594+
595+ var serviceSnapshotsJSON json.RawMessage
596+ if serviceSnapshots != nil {
597+ serviceSnapshotsJSON , err = json .Marshal (serviceSnapshots )
598+ if err != nil {
599+ return echo .NewHTTPError (http .StatusInternalServerError , "Failed to marshal service snapshots" )
600+ }
601+ }
602+
603+ err = h .server .db .UpdateBlueprint (ctx .Request ().Context (), versionId , blueprintId , userID .OrgID (), blueprintRequest .Name , desc , body , serviceSnapshotsJSON )
523604 if err != nil {
524- ctx .Logger ().Errorf ("Error updating blueprint in db: %v" , err )
605+ slog .ErrorContext (ctx .Request ().Context (), "error updating blueprint with service snapshots in db" ,
606+ "error" , err )
525607 if errors .Is (err , db .ErrBlueprintNotFound ) {
526608 return echo .NewHTTPError (http .StatusNotFound , err )
527609 }
528610 return err
529611 }
530- ctx .Logger ().Infof ("Updated blueprint %s" , blueprintId )
531612 return ctx .JSON (http .StatusCreated , ComposeResponse {
532613 Id : blueprintId ,
533614 })
@@ -681,7 +762,7 @@ func (h *Handlers) GetBlueprintComposes(ctx echo.Context, blueprintId openapi_ty
681762 composes , err := h .server .db .GetBlueprintComposes (ctx .Request ().Context (), userID .OrgID (), blueprintId , params .BlueprintVersion , since , limit , offset , ignoreImageTypeStrings )
682763 if err != nil {
683764 if errors .Is (err , db .ErrBlueprintNotFound ) {
684- return echo .NewHTTPError (http .StatusNotFound )
765+ return echo .NewHTTPError (http .StatusNotFound , err )
685766 }
686767 return err
687768 }
@@ -787,14 +868,37 @@ func (h *Handlers) FixupBlueprint(ctx echo.Context, id openapi_types.UUID) error
787868 return err
788869 }
789870 desc := common .FromPtr (blueprintRequest .Description )
871+ slog .DebugContext (ctx .Request ().Context (), "starting buildServiceSnapshots during fixup" ,
872+ "blueprint_id" , blueprintEntry .Id ,
873+ "distribution" , blueprintRequest .Distribution ,
874+ "has_openscap" , blueprintRequest .Customizations .Openscap != nil )
790875
791- err = h .server . db . UpdateBlueprint (ctx . Request (). Context (), uuid . New (), blueprintEntry . Id , userID . OrgID (), blueprintRequest .Name , desc , body )
876+ serviceSnapshots , err : = h .buildServiceSnapshots (ctx , & blueprintRequest . Customizations , blueprintRequest .Distribution )
792877 if err != nil {
793- ctx .Logger ().Errorf ("Error updating blueprint in db: %v" , err )
878+ slog .ErrorContext (ctx .Request ().Context (), "error building service snapshots during fixup" ,
879+ "blueprint_id" , blueprintEntry .Id ,
880+ "error" , err .Error ())
881+ return echo .NewHTTPError (http .StatusInternalServerError , "Failed to build compliance snapshots during fixup" )
882+ }
883+
884+ var serviceSnapshotsJSON json.RawMessage
885+ if serviceSnapshots != nil {
886+ serviceSnapshotsJSON , err = json .Marshal (serviceSnapshots )
887+ if err != nil {
888+ return echo .NewHTTPError (http .StatusInternalServerError , "Failed to marshal service snapshots" )
889+ }
890+ }
891+
892+ versionId := uuid .New ()
893+ err = h .server .db .UpdateBlueprint (ctx .Request ().Context (), versionId , blueprintEntry .Id , userID .OrgID (), blueprintRequest .Name , desc , body , serviceSnapshotsJSON )
894+ if err != nil {
895+ slog .ErrorContext (ctx .Request ().Context (), "error updating blueprint in db during fixup" ,
896+ "error" , err )
794897 if errors .Is (err , db .ErrBlueprintNotFound ) {
795898 return echo .NewHTTPError (http .StatusNotFound , err )
796899 }
797900 return err
798901 }
902+
799903 return ctx .NoContent (http .StatusCreated )
800904}
0 commit comments