@@ -350,6 +350,151 @@ func (s *AppInstallTestSuite) TestPatchAppConfigValues() {
350350 assert .Equal (t , apiError .Errors [1 ].Field , "required-password" )
351351 assert .Equal (t , apiError .Errors [1 ].Message , "Required Password is required" )
352352 })
353+
354+ // Test required hidden item should produce error
355+ s .T ().Run ("Required hidden item should produce error" , func (t * testing.T ) {
356+ // Create app config with required hidden item
357+ configWithHiddenRequired := kotsv1beta1.Config {
358+ Spec : kotsv1beta1.ConfigSpec {
359+ Groups : []kotsv1beta1.ConfigGroup {
360+ {
361+ Name : "security-group" ,
362+ Title : "Security Settings" ,
363+ Items : []kotsv1beta1.ConfigItem {
364+ {
365+ Name : "api-key" ,
366+ Type : "password" ,
367+ Title : "API Key" ,
368+ Required : true ,
369+ Hidden : true , // This item is hidden but required
370+ },
371+ {
372+ Name : "visible-setting" ,
373+ Type : "text" ,
374+ Title : "Visible Setting" ,
375+ Required : false ,
376+ Hidden : false ,
377+ },
378+ },
379+ },
380+ },
381+ },
382+ }
383+
384+ // Create an install controller with the app config
385+ apiInstance := s .createAPI (t , states .StateNew , & release.ReleaseData {
386+ AppConfig : & configWithHiddenRequired ,
387+ }, nil )
388+
389+ // Create a router and register the API routes
390+ router := mux .NewRouter ()
391+ apiInstance .RegisterRoutes (router )
392+
393+ // Create a request to patch config values without the required hidden item
394+ patchRequest := types.PatchAppConfigValuesRequest {
395+ Values : types.AppConfigValues {
396+ "visible-setting" : types.AppConfigValue {Value : "some-value" },
397+ },
398+ }
399+
400+ reqBodyBytes , err := json .Marshal (patchRequest )
401+ require .NoError (t , err )
402+
403+ // Create a request
404+ req := httptest .NewRequest (http .MethodPatch , s .baseURL + "/app/config/values" , bytes .NewReader (reqBodyBytes ))
405+ req .Header .Set ("Content-Type" , "application/json" )
406+ req .Header .Set ("Authorization" , "Bearer " + "TOKEN" )
407+ rec := httptest .NewRecorder ()
408+
409+ // Serve the request
410+ router .ServeHTTP (rec , req )
411+
412+ // Check the response - should return 400 Bad Request due to missing required hidden item
413+ assert .Equal (t , http .StatusBadRequest , rec .Code )
414+
415+ // Parse the response body
416+ var apiError types.APIError
417+ err = json .NewDecoder (rec .Body ).Decode (& apiError )
418+ require .NoError (t , err )
419+ assert .Equal (t , http .StatusBadRequest , apiError .StatusCode )
420+
421+ // Verify the error mentions the required hidden field
422+ require .Len (t , apiError .Errors , 1 )
423+ assert .Equal (t , apiError .Errors [0 ].Field , "api-key" )
424+ assert .Equal (t , apiError .Errors [0 ].Message , "API Key is required" )
425+ })
426+
427+ // Test required hidden item with predefined value should not produce error
428+ s .T ().Run ("Required hidden item with value should not produce error" , func (t * testing.T ) {
429+ // Create app config with required hidden item wtih a value
430+ configWithHiddenRequired := kotsv1beta1.Config {
431+ Spec : kotsv1beta1.ConfigSpec {
432+ Groups : []kotsv1beta1.ConfigGroup {
433+ {
434+ Name : "security-group" ,
435+ Title : "Security Settings" ,
436+ Items : []kotsv1beta1.ConfigItem {
437+ {
438+ Name : "api-key" ,
439+ Type : "password" ,
440+ Title : "API Key" ,
441+ Value : multitype .FromString ("hidden-key-value" ),
442+ Required : true ,
443+ Hidden : true , // This item is hidden but required
444+ },
445+ {
446+ Name : "visible-setting" ,
447+ Type : "text" ,
448+ Title : "Visible Setting" ,
449+ Required : false ,
450+ Hidden : false ,
451+ },
452+ },
453+ },
454+ },
455+ },
456+ }
457+
458+ // Create an install controller with the app config
459+ apiInstance := s .createAPI (t , states .StateNew , & release.ReleaseData {
460+ AppConfig : & configWithHiddenRequired ,
461+ }, nil )
462+
463+ // Create a router and register the API routes
464+ router := mux .NewRouter ()
465+ apiInstance .RegisterRoutes (router )
466+
467+ // Create a request to patch config values without the required hidden item
468+ patchRequest := types.PatchAppConfigValuesRequest {
469+ Values : types.AppConfigValues {
470+ "visible-setting" : types.AppConfigValue {Value : "some-value" },
471+ },
472+ }
473+
474+ reqBodyBytes , err := json .Marshal (patchRequest )
475+ require .NoError (t , err )
476+
477+ // Create a request
478+ req := httptest .NewRequest (http .MethodPatch , s .baseURL + "/app/config/values" , bytes .NewReader (reqBodyBytes ))
479+ req .Header .Set ("Content-Type" , "application/json" )
480+ req .Header .Set ("Authorization" , "Bearer " + "TOKEN" )
481+ rec := httptest .NewRecorder ()
482+
483+ // Serve the request
484+ router .ServeHTTP (rec , req )
485+
486+ // Check the response
487+ assert .Equal (t , http .StatusOK , rec .Code )
488+
489+ // Parse the response body
490+ var response types.AppConfigValuesResponse
491+ err = json .NewDecoder (rec .Body ).Decode (& response )
492+ require .NoError (t , err )
493+ require .NotNil (t , response .Values , "response values should not be nil" )
494+
495+ // Verify the app config values are returned from the store
496+ assert .Equal (t , "some-value" , response .Values ["visible-setting" ].Value , "visible-setting should be updated" )
497+ })
353498}
354499
355500func (s * AppInstallTestSuite ) TestTemplateAppConfig () {
@@ -678,6 +823,132 @@ func (s *AppInstallTestSuite) TestTemplateAppConfig() {
678823 require .NoError (t , err )
679824 assert .Equal (t , http .StatusBadRequest , apiError .StatusCode )
680825 })
826+
827+ // Test hidden items should not be returned
828+ s .T ().Run ("Hidden items should not be returned" , func (t * testing.T ) {
829+ // Create app config with hidden items
830+ configWithHidden := kotsv1beta1.Config {
831+ TypeMeta : metav1.TypeMeta {
832+ APIVersion : "kots.io/v1beta1" ,
833+ Kind : "Config" ,
834+ },
835+ ObjectMeta : metav1.ObjectMeta {
836+ Name : "config-with-hidden" ,
837+ },
838+ Spec : kotsv1beta1.ConfigSpec {
839+ Groups : []kotsv1beta1.ConfigGroup {
840+ {
841+ Name : "mixed-visibility" ,
842+ Title : "Mixed Visibility Group" ,
843+ Items : []kotsv1beta1.ConfigItem {
844+ {
845+ Name : "visible-item" ,
846+ Type : "text" ,
847+ Title : "Visible Item" ,
848+ Default : multitype .FromString ("visible-default" ),
849+ Value : multitype .FromString ("visible-value" ),
850+ Hidden : false ,
851+ },
852+ {
853+ Name : "hidden-item" ,
854+ Type : "text" ,
855+ Title : "Hidden Item" ,
856+ Default : multitype .FromString ("hidden-default" ),
857+ Value : multitype .FromString ("hidden-value" ),
858+ Hidden : true , // This item should not appear in the response
859+ },
860+ {
861+ Name : "hidden-password" ,
862+ Type : "password" ,
863+ Title : "Hidden Password" ,
864+ Default : multitype .FromString ("hidden-password-default" ),
865+ Value : multitype .FromString ("hidden-password-value" ),
866+ Hidden : true , // This item should not appear in the response
867+ },
868+ {
869+ Name : "another-visible-item" ,
870+ Type : "text" ,
871+ Title : "Another Visible Item" ,
872+ Default : multitype .FromString ("another-visible-default" ),
873+ Value : multitype .FromString ("another-visible-value" ),
874+ Hidden : false ,
875+ },
876+ },
877+ },
878+ },
879+ },
880+ }
881+
882+ // Create an install controller with the app config
883+ apiInstance := s .createAPI (t , states .StateNew , & release.ReleaseData {
884+ AppConfig : & configWithHidden ,
885+ }, nil )
886+
887+ // Create a router and register the API routes
888+ router := mux .NewRouter ()
889+ apiInstance .RegisterRoutes (router )
890+
891+ // Create template request
892+ templateRequest := types.TemplateAppConfigRequest {
893+ Values : types.AppConfigValues {
894+ "visible-item" : {Value : "user-visible-value" },
895+ "hidden-item" : {Value : "user-hidden-value" }, // Even if user provides this, it shouldn't appear
896+ "another-visible-item" : {Value : "user-another-visible-value" },
897+ },
898+ }
899+
900+ reqBodyBytes , err := json .Marshal (templateRequest )
901+ require .NoError (t , err )
902+
903+ // Create a request
904+ req := httptest .NewRequest (http .MethodPost , s .baseURL + "/app/config/template" , bytes .NewReader (reqBodyBytes ))
905+ req .Header .Set ("Content-Type" , "application/json" )
906+ req .Header .Set ("Authorization" , "Bearer TOKEN" )
907+ rec := httptest .NewRecorder ()
908+
909+ // Serve the request
910+ router .ServeHTTP (rec , req )
911+
912+ // Check the response
913+ require .Equal (t , http .StatusOK , rec .Code )
914+ assert .Equal (t , "application/json" , rec .Header ().Get ("Content-Type" ))
915+
916+ // Parse the response body
917+ var response types.AppConfig
918+ err = json .NewDecoder (rec .Body ).Decode (& response )
919+ require .NoError (t , err )
920+
921+ // Verify hidden items are filtered out
922+ require .Len (t , response .Groups , 1 , "group should be present" )
923+ group := response .Groups [0 ]
924+ assert .Equal (t , "Mixed Visibility Group" , group .Title )
925+
926+ // Should only have the visible items (hidden items should be filtered out)
927+ require .Len (t , group .Items , 2 , "only visible items should be present" )
928+
929+ // Check that only visible items are present
930+ visibleItemNames := make ([]string , len (group .Items ))
931+ for i , item := range group .Items {
932+ visibleItemNames [i ] = item .Name
933+ }
934+
935+ assert .Contains (t , visibleItemNames , "visible-item" , "visible-item should be present" )
936+ assert .Contains (t , visibleItemNames , "another-visible-item" , "another-visible-item should be present" )
937+ assert .NotContains (t , visibleItemNames , "hidden-item" , "hidden-item should not be present" )
938+ assert .NotContains (t , visibleItemNames , "hidden-password" , "hidden-password should not be present" )
939+
940+ // Verify the visible items have correct values
941+ for _ , item := range group .Items {
942+ switch item .Name {
943+ case "visible-item" :
944+ assert .Equal (t , "user-visible-value" , item .Value .String (), "visible-item should have user-provided value" )
945+ assert .False (t , item .Hidden , "visible-item should not be hidden" )
946+ case "another-visible-item" :
947+ assert .Equal (t , "user-another-visible-value" , item .Value .String (), "another-visible-item should have user-provided value" )
948+ assert .False (t , item .Hidden , "another-visible-item should not be hidden" )
949+ }
950+ }
951+ })
681952}
682953
683954// Runner function that executes the suite for both install types
0 commit comments