@@ -198,7 +198,12 @@ if Code.ensure_loaded?(OpenApiSpex) do
198198 defp all_resources_requiring_filter_schemas ( domains ) do
199199 domains
200200 |> Enum . flat_map ( & Ash.Domain.Info . resources / 1 )
201- |> Enum . reject ( & Enum . empty? ( AshJsonApi.Resource.Info . routes ( & 1 , domains ) ) )
201+ |> Enum . reject ( fn resource ->
202+ resource
203+ |> AshJsonApi.Resource.Info . routes ( domains )
204+ |> Enum . filter ( & route_visible? ( resource , & 1 ) )
205+ |> Enum . empty? ( )
206+ end )
202207 |> with_all_related_resources ( )
203208 |> Enum . filter ( fn resource ->
204209 AshJsonApi.Resource.Info . type ( resource ) &&
@@ -209,7 +214,11 @@ if Code.ensure_loaded?(OpenApiSpex) do
209214 defp with_all_related_resources ( resources , checked \\ [ ] ) do
210215 resources
211216 |> Enum . reject ( & ( & 1 in checked ) )
212- |> Enum . flat_map ( & Ash.Resource.Info . public_relationships / 1 )
217+ |> Enum . flat_map ( fn resource ->
218+ resource
219+ |> Ash.Resource.Info . public_relationships ( )
220+ |> filter_shown_fields ( resource )
221+ end )
213222 |> Enum . map ( & & 1 . destination )
214223 |> Enum . reject ( & ( & 1 in resources ) )
215224 |> case do
@@ -233,7 +242,11 @@ if Code.ensure_loaded?(OpenApiSpex) do
233242 domains
234243 |> Stream . flat_map ( & Ash.Domain.Info . resources / 1 )
235244 |> Stream . reject ( & Enum . empty? ( AshJsonApi.Resource.Info . routes ( & 1 , domains ) ) )
236- |> Stream . flat_map ( & Ash.Resource.Info . relationships / 1 )
245+ |> Stream . flat_map ( fn resource ->
246+ resource
247+ |> Ash.Resource.Info . relationships ( )
248+ |> filter_shown_fields ( resource )
249+ end )
237250 |> Stream . filter ( & & 1 . public? )
238251 |> Enum . any? ( & ( & 1 . destination == resource ) )
239252 end
@@ -252,6 +265,18 @@ if Code.ensure_loaded?(OpenApiSpex) do
252265 action && action . type == :read
253266 end
254267
268+ defp show_field? ( resource , % { name: name } ) do
269+ AshJsonApi.Resource.Info . show_field? ( resource , name )
270+ end
271+
272+ defp show_field? ( resource , field ) do
273+ AshJsonApi.Resource.Info . show_field? ( resource , field )
274+ end
275+
276+ defp filter_shown_fields ( fields , resource ) do
277+ Enum . filter ( fields , & show_field? ( resource , & 1 ) )
278+ end
279+
255280 defp resource_filter_schemas ( domains , resource , acc ) do
256281 { field_types , acc } = filter_field_types ( resource , acc )
257282
@@ -381,6 +406,8 @@ if Code.ensure_loaded?(OpenApiSpex) do
381406 fields || AshJsonApi.Resource.Info . default_fields ( resource ) ||
382407 Enum . map ( Ash.Resource.Info . public_attributes ( resource ) , & & 1 . name )
383408
409+ fields = Enum . filter ( fields , & show_field? ( resource , & 1 ) )
410+
384411 { properties , acc } = resource_attributes ( resource , fields , :json , acc )
385412
386413 schema =
@@ -399,6 +426,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
399426 defp required_attributes ( resource ) do
400427 resource
401428 |> Ash.Resource.Info . public_attributes ( )
429+ |> filter_shown_fields ( resource )
402430 |> Enum . reject ( & ( & 1 . allow_nil? || AshJsonApi.Resource . only_primary_key? ( resource , & 1 . name ) ) )
403431 |> Enum . map ( fn attr ->
404432 AshJsonApi.Resource.Info . field_to_json_key ( resource , attr . name )
@@ -420,6 +448,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
420448 Ash.Resource.Info . public_aggregates ( resource )
421449 |> AshJsonApi.JsonSchema . set_aggregate_constraints ( resource )
422450 )
451+ |> filter_shown_fields ( resource )
423452 |> Enum . map ( fn
424453 % Ash.Resource.Aggregate { } = agg ->
425454 field =
@@ -1343,6 +1372,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
13431372 defp resource_relationships ( resource ) do
13441373 resource
13451374 |> Ash.Resource.Info . public_relationships ( )
1375+ |> filter_shown_fields ( resource )
13461376 |> Enum . filter ( fn % { destination: destination } ->
13471377 AshJsonApi.Resource.Info . type ( destination )
13481378 end )
@@ -1517,7 +1547,10 @@ if Code.ensure_loaded?(OpenApiSpex) do
15171547 domain
15181548 |> resources ( )
15191549 |> Enum . flat_map_reduce ( acc , fn resource , acc ->
1520- routes = AshJsonApi.Resource.Info . routes ( resource , all_domains )
1550+ routes =
1551+ resource
1552+ |> AshJsonApi.Resource.Info . routes ( all_domains )
1553+ |> Enum . filter ( & route_visible? ( resource , & 1 ) )
15211554
15221555 { route_operations , acc } =
15231556 Enum . map_reduce ( routes , acc , fn route , acc ->
@@ -1535,6 +1568,12 @@ if Code.ensure_loaded?(OpenApiSpex) do
15351568 { final_paths , final_acc }
15361569 end
15371570
1571+ defp route_visible? ( _resource , % { relationship: nil } ) , do: true
1572+
1573+ defp route_visible? ( resource , % { relationship: relationship } ) do
1574+ show_field? ( resource , relationship )
1575+ end
1576+
15381577 @ spec route_operation (
15391578 Route . t ( ) ,
15401579 domain :: module ,
@@ -1745,6 +1784,13 @@ if Code.ensure_loaded?(OpenApiSpex) do
17451784 end )
17461785 )
17471786 |> Enum . filter ( & & 1 )
1787+ |> Enum . reject ( fn
1788+ % Ash.Resource.Attribute { name: name } ->
1789+ ! show_field? ( resource , name ) && to_string ( name ) not in route_params
1790+
1791+ _ ->
1792+ false
1793+ end )
17481794 |> Enum . reduce ( { [ ] , acc } , fn argument_or_attribute , { list , acc } ->
17491795 { schema , acc } =
17501796 resource_write_attribute_type ( argument_or_attribute , resource , action . type , acc )
@@ -1859,6 +1905,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
18591905 sorts =
18601906 resource
18611907 |> AshJsonApi.JsonSchema . sortable_fields ( )
1908+ |> filter_shown_fields ( resource )
18621909 |> Enum . flat_map ( fn attr ->
18631910 name = AshJsonApi.Resource.Info . field_to_json_key ( resource , attr . name )
18641911 [ name , "-" <> name , "\\ +\\ +" <> name , "--" <> name ]
@@ -1992,6 +2039,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
19922039 resource
19932040 |> AshJsonApi.Resource.Info . includes ( )
19942041 |> all_paths ( )
2042+ |> Enum . filter ( & visible_relationship_path? ( resource , & 1 ) )
19952043 |> Enum . map ( & Enum . join ( & 1 , "." ) )
19962044
19972045 % Parameter {
@@ -2016,6 +2064,10 @@ if Code.ensure_loaded?(OpenApiSpex) do
20162064 # Get all paginated relationship paths
20172065 paginated_paths =
20182066 paginated_includes
2067+ |> Enum . filter ( fn
2068+ path when is_list ( path ) -> visible_relationship_path? ( resource , path )
2069+ atom when is_atom ( atom ) -> visible_relationship_path? ( resource , [ atom ] )
2070+ end )
20192071 |> Enum . map ( fn
20202072 path when is_list ( path ) -> Enum . join ( path , "." )
20212073 atom when is_atom ( atom ) -> to_string ( atom )
@@ -2041,11 +2093,10 @@ if Code.ensure_loaded?(OpenApiSpex) do
20412093 type = AshJsonApi.Resource.Info . type ( resource )
20422094
20432095 example =
2044- Enum . join (
2045- AshJsonApi.Resource.Info . default_fields ( resource ) ||
2046- Enum . map ( Ash.Resource.Info . public_attributes ( resource ) , & & 1 . name ) ,
2047- ","
2048- )
2096+ ( AshJsonApi.Resource.Info . default_fields ( resource ) ||
2097+ Enum . map ( Ash.Resource.Info . public_attributes ( resource ) , & & 1 . name ) )
2098+ |> Enum . filter ( & show_field? ( resource , & 1 ) )
2099+ |> Enum . join ( "," )
20492100
20502101 % Parameter {
20512102 name: :fields ,
@@ -2070,6 +2121,26 @@ if Code.ensure_loaded?(OpenApiSpex) do
20702121 }
20712122 end
20722123
2124+ defp visible_relationship_path? ( resource , path ) do
2125+ path
2126+ |> List . wrap ( )
2127+ |> Enum . reduce_while ( resource , fn relationship_name , current_resource ->
2128+ relationship = Ash.Resource.Info . public_relationship ( current_resource , relationship_name )
2129+
2130+ cond do
2131+ is_nil ( relationship ) ->
2132+ { :halt , false }
2133+
2134+ ! show_field? ( current_resource , relationship_name ) ->
2135+ { :halt , false }
2136+
2137+ true ->
2138+ { :cont , relationship . destination }
2139+ end
2140+ end )
2141+ |> then ( & ( & 1 != false ) )
2142+ end
2143+
20732144 @ spec read_argument_parameters (
20742145 Route . t ( ) ,
20752146 resource :: module ,
@@ -2394,12 +2465,13 @@ if Code.ensure_loaded?(OpenApiSpex) do
23942465 [ ]
23952466
23962467 :update ->
2397- action . require_attributes
2468+ Enum . filter ( action . require_attributes , & show_field? ( resource , & 1 ) )
23982469
23992470 _ ->
24002471 resource
24012472 |> Ash.Resource.Info . attributes ( )
24022473 |> Enum . filter ( & ( & 1 . name in action . accept && & 1 . writable? ) )
2474+ |> filter_shown_fields ( resource )
24032475 |> Enum . reject (
24042476 & ( & 1 . name in filtered_arguments || & 1 . allow_nil? || not is_nil ( & 1 . default ) ||
24052477 & 1 . generated? ||
@@ -2417,6 +2489,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
24172489
24182490 require_attributes =
24192491 Map . get ( action , :require_attributes , [ ] )
2492+ |> Enum . filter ( & show_field? ( resource , & 1 ) )
24202493 |> Enum . map ( & AshJsonApi.Resource.Info . field_to_json_key ( resource , & 1 ) )
24212494
24222495 Enum . uniq ( attribute_names ++ argument_names ++ require_attributes )
@@ -2438,6 +2511,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
24382511 resource
24392512 |> Ash.Resource.Info . attributes ( )
24402513 |> Enum . filter ( & ( & 1 . name in action . accept && & 1 . writable? ) )
2514+ |> filter_shown_fields ( resource )
24412515 |> Enum . reduce ( { % { } , acc } , fn attribute , { attrs , acc } ->
24422516 { schema , acc } =
24432517 resource_write_attribute_type ( attribute , resource , action . type , acc , format )
@@ -2492,6 +2566,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
24922566 defp required_relationship_attributes ( resource , relationship_arguments , action ) do
24932567 action . arguments
24942568 |> Enum . filter ( & has_relationship_argument? ( relationship_arguments , & 1 . name ) )
2569+ |> filter_shown_fields ( resource )
24952570 |> Enum . reject ( & & 1 . allow_nil? )
24962571 |> Enum . map ( fn arg ->
24972572 AshJsonApi.Resource.Info . argument_to_json_key ( resource , action . name , arg . name )
@@ -2503,6 +2578,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
25032578 defp write_relationships ( resource , relationship_arguments , action ) do
25042579 action . arguments
25052580 |> Enum . filter ( & has_relationship_argument? ( relationship_arguments , & 1 . name ) )
2581+ |> filter_shown_fields ( resource )
25062582 |> Map . new ( fn argument ->
25072583 data = resource_write_relationship_field_data ( resource , argument )
25082584
@@ -2747,11 +2823,15 @@ if Code.ensure_loaded?(OpenApiSpex) do
27472823 do: relationship_destination ( resource , include ) |> List . wrap ( )
27482824
27492825 defp relationship_destination ( resource , include ) do
2750- resource
2751- |> Ash.Resource.Info . public_relationship ( include )
2752- |> case do
2753- % { destination: destination } -> destination
2754- _ -> nil
2826+ if show_field? ( resource , include ) do
2827+ resource
2828+ |> Ash.Resource.Info . public_relationship ( include )
2829+ |> case do
2830+ % { destination: destination } -> destination
2831+ _ -> nil
2832+ end
2833+ else
2834+ nil
27552835 end
27562836 end
27572837
@@ -2765,6 +2845,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
27652845 defp filter_attribute_types ( resource , acc ) do
27662846 resource
27672847 |> Ash.Resource.Info . public_attributes ( )
2848+ |> filter_shown_fields ( resource )
27682849 |> Enum . filter ( & filterable? ( & 1 , resource ) )
27692850 |> Enum . reduce ( { [ ] , acc } , fn attribute , { results , acc } ->
27702851 { result , acc } = filter_type ( attribute , resource , acc )
@@ -2775,6 +2856,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
27752856 defp filter_aggregate_types ( resource , acc ) do
27762857 resource
27772858 |> Ash.Resource.Info . public_aggregates ( )
2859+ |> filter_shown_fields ( resource )
27782860 |> Enum . filter ( & filterable? ( & 1 , resource ) )
27792861 |> Enum . reduce ( { [ ] , acc } , fn aggregate , { results , acc } ->
27802862 { result , acc } = filter_type ( aggregate , resource , acc )
@@ -2785,6 +2867,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
27852867 defp filter_calculation_types ( resource , acc ) do
27862868 resource
27872869 |> Ash.Resource.Info . public_calculations ( )
2870+ |> filter_shown_fields ( resource )
27882871 |> Enum . filter ( & filterable? ( & 1 , resource ) )
27892872 |> Enum . reduce ( { [ ] , acc } , fn calculation , { results , acc } ->
27902873 { result , acc } = filter_type ( calculation , resource , acc )
@@ -2987,6 +3070,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
29873070
29883071 resource
29893072 |> Ash.Resource.Info . public_relationships ( )
3073+ |> filter_shown_fields ( resource )
29903074 |> Enum . filter (
29913075 & ( & 1 . destination in all_resources &&
29923076 AshJsonApi.Resource.Info . derive_filter? ( & 1 . destination ) &&
@@ -3006,6 +3090,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
30063090 if Ash.DataLayer . data_layer_can? ( resource , :expression_calculation ) do
30073091 resource
30083092 |> Ash.Resource.Info . public_calculations ( )
3093+ |> filter_shown_fields ( resource )
30093094 |> Enum . filter ( & filterable? ( & 1 , resource ) )
30103095 |> Enum . map ( fn calculation ->
30113096 { calculation . name ,
@@ -3021,6 +3106,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
30213106 defp attribute_filter_fields ( resource ) do
30223107 resource
30233108 |> Ash.Resource.Info . public_attributes ( )
3109+ |> filter_shown_fields ( resource )
30243110 |> Enum . filter ( & filterable? ( & 1 , resource ) )
30253111 |> Enum . map ( fn attribute ->
30263112 { attribute . name ,
@@ -3034,6 +3120,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
30343120 if Ash.DataLayer . data_layer_can? ( resource , :aggregate_filter ) do
30353121 resource
30363122 |> Ash.Resource.Info . public_aggregates ( )
3123+ |> filter_shown_fields ( resource )
30373124 |> Enum . filter ( & filterable? ( & 1 , resource ) )
30383125 |> Enum . map ( fn aggregate ->
30393126 { aggregate . name ,
0 commit comments