@@ -14,104 +14,137 @@ class GraphsController < ApplicationController
1414
1515 def show
1616 authorize :inspect , :graph?
17- @primary_type = safe_get_primary_type
18- if @primary_type . nil?
17+ if primary_type . nil?
1918 render plain :
2019 "You don't have permission to view object type: #{ params [ :object_type ] . to_s . downcase . singularize } " ,
2120 status : :bad_request and return
2221 end
23- @primary_id = params [ :object_id ]
2422
2523 # Set default relationships when loading a page for the first time
2624 if params [ :relationships ] . blank? &&
27- GraphRecords ::DEFAULT_TRAVERSALS . key? ( @ primary_type)
28- default_rels = GraphRecords ::DEFAULT_TRAVERSALS [ @ primary_type] || { }
25+ GraphRecords ::DEFAULT_TRAVERSALS . key? ( primary_type )
26+ default_rels = GraphRecords ::DEFAULT_TRAVERSALS [ primary_type ] || { }
2927
3028 new_params = params . to_unsafe_h . merge ( "relationships" => default_rels )
3129 redirect_to inspect_path ( new_params ) and return
3230 end
3331
34- @object = @primary_type . to_s . classify . constantize . find ( @primary_id )
35-
36- @traversals_config = build_traversals_config
37- @graph_params = build_graph_params
38- set_pii_settings
39-
4032 @graph_record =
4133 GraphRecords . new (
42- traversals_config : @traversals_config ,
43- primary_type : @primary_type ,
34+ traversals_config :,
35+ primary_type :,
4436 clickable : true ,
45- show_pii : @show_pii
37+ show_pii :
4638 )
47- @mermaid = @graph_record . graph ( **@ graph_params) . join ( "\n " )
39+ @mermaid = @graph_record . graph ( **graph_params ) . join ( "\n " )
4840 end
4941
5042 private
5143
52- def set_pii_settings
53- @user_is_allowed_to_access_pii = policy ( :inspect ) . show_pii?
54- @show_pii =
55- @user_is_allowed_to_access_pii &&
56- ( params [ :show_pii ] || SHOW_PII_BY_DEFAULT )
44+ def show_pii
45+ @show_pii ||=
46+ user_is_allowed_to_access_pii && !sensitive_patient_in_graph &&
47+ pii_access_requested_by_user
5748 end
5849
59- def build_traversals_config
60- traversals_config = { }
61- to_process = Set . new ( [ @primary_type ] )
62- processed = Set . new
50+ def user_is_allowed_to_access_pii
51+ @user_is_allowed_to_access_pii ||= policy ( :inspect ) . show_pii?
52+ end
6353
64- # Process types until we've explored all connected relationships
65- while ( type = to_process . first )
66- to_process . delete ( type )
67- processed . add ( type )
54+ def sensitive_patient_in_graph
55+ @sensitive_patient_in_graph ||=
56+ begin
57+ graph_with_pii =
58+ GraphRecords . new (
59+ traversals_config :,
60+ primary_type :,
61+ clickable : true ,
62+ show_pii : true
63+ )
64+ graph_with_pii . graph ( **graph_params )
65+ graph_with_pii . patients_with_pii_in_graph . any? ( &:restricted? )
66+ end
67+ end
6868
69- selected_rels =
70- Array ( params . dig ( :relationships , type ) ) . reject ( &:blank? ) . map ( &:to_sym )
69+ def pii_access_requested_by_user
70+ @pii_access_requested_by_user ||= params [ :show_pii ] || SHOW_PII_BY_DEFAULT
71+ end
7172
72- traversals_config [ type ] = selected_rels
73+ def traversals_config
74+ @traversals_config ||=
75+ begin
76+ traversals = { }
77+ to_process = Set . new ( [ primary_type ] )
78+ processed = Set . new
79+
80+ # Process types until we've explored all connected relationships
81+ while ( type = to_process . first )
82+ to_process . delete ( type )
83+ processed . add ( type )
84+
85+ selected_rels =
86+ Array ( params . dig ( :relationships , type ) ) . reject ( &:blank? ) . map (
87+ &:to_sym
88+ )
7389
74- # Add target types to process queue
75- klass = type . to_s . classify . constantize
76- selected_rels . each do |rel |
77- association = klass . reflect_on_association ( rel )
78- next unless association
90+ traversals [ type ] = selected_rels
7991
80- target_type = association . klass . name . underscore . to_sym
81- to_process . add ( target_type ) unless processed . include? ( target_type )
82- end
83- end
92+ # Add target types to process queue
93+ klass = type . to_s . classify . constantize
94+ selected_rels . each do |rel |
95+ association = klass . reflect_on_association ( rel )
96+ next unless association
8497
85- traversals_config
98+ target_type = association . klass . name . underscore . to_sym
99+ to_process . add ( target_type ) unless processed . include? ( target_type )
100+ end
101+ end
102+
103+ traversals
104+ end
86105 end
87106
88- def build_graph_params
89- graph_params = { @primary_type => [ @object . id ] }
90-
91- if params [ :additional_ids ] . present?
92- params [ :additional_ids ] . each do |type , ids_string |
93- next if ids_string . blank?
94- additional_ids = ids_string . split ( "," ) . map { |s | s . strip . to_i }
95- next unless additional_ids . any?
96- type_sym = type . to_sym
97- graph_params [ type_sym ] ||= [ ]
98- graph_params [ type_sym ] . concat ( additional_ids )
107+ def graph_params
108+ @graph_params ||=
109+ begin
110+ graph_params = { primary_type => [ primary_object . id ] }
111+
112+ if params [ :additional_ids ] . present?
113+ params [ :additional_ids ] . each do |type , ids_string |
114+ next if ids_string . blank?
115+ additional_ids = ids_string . split ( "," ) . map { |s | s . strip . to_i }
116+ next unless additional_ids . any?
117+ type_sym = type . to_sym
118+ graph_params [ type_sym ] ||= [ ]
119+ graph_params [ type_sym ] . concat ( additional_ids )
120+ end
121+ end
122+
123+ graph_params
99124 end
100- end
125+ end
101126
102- graph_params
127+ def primary_type
128+ @primary_type ||=
129+ begin
130+ singular_type = params [ :object_type ] . downcase . singularize
131+ return nil unless GraphRecords ::ALLOWED_TYPES . include? ( singular_type )
132+ singular_type . to_sym
133+ end
103134 end
104135
105- def safe_get_primary_type
106- singular_type = params [ :object_type ] . downcase . singularize
107- return nil unless GraphRecords ::ALLOWED_TYPES . include? ( singular_type )
108- singular_type . to_sym
136+ def primary_object
137+ @primary_object ||=
138+ begin
139+ @primary_id = params [ :object_id ]
140+ primary_type . to_s . classify . constantize . find ( @primary_id )
141+ end
109142 end
110143
111144 def pii_accessed?
112- return false unless @ show_pii
145+ return false unless show_pii
113146
114- build_traversals_config . any? do |from_type , rels |
147+ traversals_config . any? do |from_type , rels |
115148 GraphRecords ::EXTRA_DETAIL_WHITELIST_WITH_PII . key? (
116149 from_type . name . underscore . to_sym
117150 ) ||
@@ -142,7 +175,7 @@ def record_access_log_entry
142175 controller : "graph" ,
143176 action : "show_pii" ,
144177 request_details : {
145- primary_type : @primary_type ,
178+ primary_type :,
146179 primary_id : @primary_id ,
147180 additional_ids : additional_ids . presence ,
148181 visible_fields : request_details
0 commit comments