PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
kcenon::pacs::ihe::xds::registry_query::impl Class Reference
Collaboration diagram for kcenon::pacs::ihe::xds::registry_query::impl:
Collaboration graph

Public Member Functions

 impl (http_options opts, signing_material signing)
 
void set_audit_sink (std::shared_ptr< kcenon::pacs::security::xds_audit_sink > sink)
 
kcenon::common::Result< registry_query_result > find_documents (const std::string &patient_id, const registry_query_options &options)
 
kcenon::common::Result< registry_query_result > get_documents (const std::vector< std::string > &uuids)
 

Private Member Functions

kcenon::common::Result< registry_query_result > execute (const registry_query_request &req, detail::stored_query_kind kind)
 
void audit_find (const std::string &patient_id, const kcenon::common::Result< registry_query_result > &r)
 
void audit_get (const std::vector< std::string > &uuids, const kcenon::common::Result< registry_query_result > &r)
 

Private Attributes

http_options opts_
 
signing_material signing_
 
std::shared_ptr< kcenon::pacs::security::xds_audit_sink > audit_sink_
 

Detailed Description

Definition at line 76 of file registry_query.cpp.

Constructor & Destructor Documentation

◆ impl()

kcenon::pacs::ihe::xds::registry_query::impl::impl ( http_options opts,
signing_material signing )
inline

Definition at line 78 of file registry_query.cpp.

79 : opts_(std::move(opts)), signing_(std::move(signing)) {}

Member Function Documentation

◆ audit_find()

void kcenon::pacs::ihe::xds::registry_query::impl::audit_find ( const std::string & patient_id,
const kcenon::common::Result< registry_query_result > & r )
inlineprivate

Definition at line 231 of file registry_query.cpp.

232 {
233 if (!audit_sink_) return;
234 kcenon::pacs::security::xds_iti18_event e;
235 e.registry_endpoint = opts_.endpoint;
236 e.query_kind =
237 kcenon::pacs::security::xds_iti18_event::kind::find_documents;
238 e.patient_id = patient_id;
239 if (r.is_ok()) {
241 } else {
242 e.outcome =
244 e.failure_description = r.error().message;
245 }
246 audit_sink_->on_iti18_query(e);
247 }
std::shared_ptr< kcenon::pacs::security::xds_audit_sink > audit_sink_
constexpr dicom_tag patient_id
Patient ID.

References audit_sink_, kcenon::pacs::ihe::xds::http_options::endpoint, opts_, kcenon::pacs::security::serious_failure, and kcenon::pacs::security::success.

Referenced by find_documents().

Here is the caller graph for this function:

◆ audit_get()

void kcenon::pacs::ihe::xds::registry_query::impl::audit_get ( const std::vector< std::string > & uuids,
const kcenon::common::Result< registry_query_result > & r )
inlineprivate

Definition at line 249 of file registry_query.cpp.

250 {
251 if (!audit_sink_) return;
252 kcenon::pacs::security::xds_iti18_event e;
253 e.registry_endpoint = opts_.endpoint;
254 e.query_kind =
255 kcenon::pacs::security::xds_iti18_event::kind::get_documents;
256 e.document_uuids = uuids;
257 if (r.is_ok()) {
259 } else {
260 e.outcome =
262 e.failure_description = r.error().message;
263 }
264 audit_sink_->on_iti18_query(e);
265 }

References audit_sink_, kcenon::pacs::ihe::xds::http_options::endpoint, opts_, kcenon::pacs::security::serious_failure, and kcenon::pacs::security::success.

Referenced by get_documents().

Here is the caller graph for this function:

◆ execute()

kcenon::common::Result< registry_query_result > kcenon::pacs::ihe::xds::registry_query::impl::execute ( const registry_query_request & req,
detail::stored_query_kind kind )
inlineprivate

Definition at line 183 of file registry_query.cpp.

185 {
186 auto env_result = detail::build_iti18_envelope(req, kind);
187 if (env_result.is_err()) {
188 return kcenon::common::make_error<registry_query_result>(
189 env_result.error());
190 }
191 auto env = env_result.value();
192
193 auto sign_result = detail::sign_envelope(
196 if (sign_result.is_err()) {
197 return kcenon::common::make_error<registry_query_result>(
198 sign_result.error());
199 }
200
201 // Per-call copy: the ITI-18 action is specific to this transaction
202 // and must not mutate the shared opts_ member, so other transaction
203 // types sharing the same http_options template do not pick up a
204 // stale action from a previous call.
205 http_options call_opts = opts_;
206 call_opts.soap_action = kIti18SoapAction;
207
208 auto http_result =
209 detail::http_post(call_opts, kSoapContentType, env.xml);
210 if (http_result.is_err()) {
211 return kcenon::common::make_error<registry_query_result>(
212 http_result.error());
213 }
214 auto response = http_result.value();
215
216 // Verify the signature on the response envelope before trusting
217 // its status attribute or any entry it carries. An unsigned
218 // "Failure" response could otherwise be used to deny service or
219 // mask real successful queries; this check short-circuits before
220 // parse_query_response sees the body.
221 auto verify = detail::verify_envelope_integrity(response.body);
222 if (verify.is_err()) {
223 auto err = verify.error();
224 err.code = map_signature_error(err.code);
225 return kcenon::common::make_error<registry_query_result>(err);
226 }
227
228 return detail::parse_query_response(response.body);
229 }
kcenon::common::Result< built_envelope > build_iti18_envelope(const registry_query_request &req, stored_query_kind kind)
Build a SOAP envelope for ITI-18 from a registry_query_request.
kcenon::common::Result< http_response > http_post(const http_options &opts, const std::string &content_type, const std::string &body)
POST body to opts.endpoint with the given Content-Type.
kcenon::common::Result< bool > sign_envelope(built_envelope &env, std::string_view cert_pem, std::string_view key_pem, std::string_view key_password)
Sign the body + timestamp of env in place.
kcenon::common::Result< registry_query_result > parse_query_response(const std::string &root_xml)
Parse an AdhocQueryResponse envelope into a registry_query_result.
kcenon::common::Result< bool > verify_envelope_integrity(std::string_view signed_xml)
Verify the structural integrity of a previously signed envelope against the certificate embedded in i...

References kcenon::pacs::ihe::xds::detail::build_iti18_envelope(), kcenon::pacs::ihe::xds::signing_material::certificate_pem, kcenon::pacs::ihe::xds::detail::http_post(), opts_, kcenon::pacs::ihe::xds::detail::parse_query_response(), kcenon::pacs::ihe::xds::signing_material::private_key_password, kcenon::pacs::ihe::xds::signing_material::private_key_pem, kcenon::pacs::ihe::xds::detail::sign_envelope(), signing_, kcenon::pacs::ihe::xds::http_options::soap_action, and kcenon::pacs::ihe::xds::detail::verify_envelope_integrity().

Referenced by find_documents(), and get_documents().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_documents()

kcenon::common::Result< registry_query_result > kcenon::pacs::ihe::xds::registry_query::impl::find_documents ( const std::string & patient_id,
const registry_query_options & options )
inline

Definition at line 86 of file registry_query.cpp.

88 {
89 auto do_audit =
91 audit_find(patient_id, r);
92 return r;
93 };
94
95 if (patient_id.empty()) {
96 return do_audit(kcenon::common::make_error<registry_query_result>(
97 static_cast<int>(
99 "find_documents: patient_id is empty",
100 std::string(error_source)));
101 }
102 if (contains_slot_literal_metachar(patient_id)) {
103 return do_audit(kcenon::common::make_error<registry_query_result>(
104 static_cast<int>(
106 "find_documents: patient_id contains a character that is "
107 "not legal inside an ebRIM StoredQuery slot literal "
108 "('(),\\' or control character)",
109 std::string(error_source)));
110 }
111 for (const auto& s : options.status_values) {
112 if (contains_slot_literal_metachar(s)) {
113 return do_audit(
114 kcenon::common::make_error<registry_query_result>(
115 static_cast<int>(
117 "find_documents: options.status_values contains a "
118 "slot-literal metacharacter",
119 std::string(error_source)));
120 }
121 }
122 if (contains_slot_literal_metachar(options.creation_time_from) ||
123 contains_slot_literal_metachar(options.creation_time_to)) {
124 return do_audit(kcenon::common::make_error<registry_query_result>(
125 static_cast<int>(
127 "find_documents: options.creation_time_* contains a "
128 "slot-literal metacharacter",
129 std::string(error_source)));
130 }
131
132 registry_query_request req;
133 req.patient_id = patient_id;
134 req.options = options;
135
136 return do_audit(
138 }
void audit_find(const std::string &patient_id, const kcenon::common::Result< registry_query_result > &r)
kcenon::common::Result< registry_query_result > execute(const registry_query_request &req, detail::stored_query_kind kind)
constexpr std::string_view error_source
Short identifier used as the "source" field of make_error.
Definition errors.h:95

References audit_find(), kcenon::pacs::ihe::xds::registry_query_options::creation_time_from, kcenon::pacs::ihe::xds::registry_query_options::creation_time_to, kcenon::pacs::ihe::xds::error_source, execute(), kcenon::pacs::ihe::xds::detail::find_documents, kcenon::pacs::ihe::xds::registry_query_request::options, kcenon::pacs::ihe::xds::registry_query_request::patient_id, kcenon::pacs::ihe::xds::registry_query_invalid_patient_id, kcenon::pacs::ihe::xds::registry_query_missing_patient_id, and kcenon::pacs::ihe::xds::registry_query_options::status_values.

Here is the call graph for this function:

◆ get_documents()

kcenon::common::Result< registry_query_result > kcenon::pacs::ihe::xds::registry_query::impl::get_documents ( const std::vector< std::string > & uuids)
inline

Definition at line 140 of file registry_query.cpp.

141 {
142 auto do_audit =
144 audit_get(uuids, r);
145 return r;
146 };
147
148 if (uuids.empty()) {
149 return do_audit(kcenon::common::make_error<registry_query_result>(
150 static_cast<int>(
152 "get_documents: uuids is empty",
153 std::string(error_source)));
154 }
155 for (const auto& u : uuids) {
156 if (u.empty()) {
157 return do_audit(
158 kcenon::common::make_error<registry_query_result>(
159 static_cast<int>(
161 "get_documents: uuids contains an empty element",
162 std::string(error_source)));
163 }
164 if (contains_slot_literal_metachar(u)) {
165 return do_audit(
166 kcenon::common::make_error<registry_query_result>(
167 static_cast<int>(
169 "get_documents: uuids contains an element with a "
170 "slot-literal metacharacter",
171 std::string(error_source)));
172 }
173 }
174
175 registry_query_request req;
176 req.document_uuids = uuids;
177
178 return do_audit(
180 }
void audit_get(const std::vector< std::string > &uuids, const kcenon::common::Result< registry_query_result > &r)

References audit_get(), kcenon::pacs::ihe::xds::registry_query_request::document_uuids, kcenon::pacs::ihe::xds::error_source, execute(), kcenon::pacs::ihe::xds::detail::get_documents, kcenon::pacs::ihe::xds::registry_query_empty_uuid_list, and kcenon::pacs::ihe::xds::registry_query_missing_document_uuid.

Referenced by kcenon::pacs::ihe::xds::registry_query::get_documents().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_audit_sink()

void kcenon::pacs::ihe::xds::registry_query::impl::set_audit_sink ( std::shared_ptr< kcenon::pacs::security::xds_audit_sink > sink)
inline

Definition at line 81 of file registry_query.cpp.

82 {
83 audit_sink_ = std::move(sink);
84 }

References audit_sink_.

Referenced by kcenon::pacs::ihe::xds::registry_query::set_audit_sink().

Here is the caller graph for this function:

Member Data Documentation

◆ audit_sink_

std::shared_ptr<kcenon::pacs::security::xds_audit_sink> kcenon::pacs::ihe::xds::registry_query::impl::audit_sink_
private

Definition at line 269 of file registry_query.cpp.

Referenced by audit_find(), audit_get(), and set_audit_sink().

◆ opts_

http_options kcenon::pacs::ihe::xds::registry_query::impl::opts_
private

Definition at line 267 of file registry_query.cpp.

Referenced by audit_find(), audit_get(), and execute().

◆ signing_

signing_material kcenon::pacs::ihe::xds::registry_query::impl::signing_
private

Definition at line 268 of file registry_query.cpp.

Referenced by execute().


The documentation for this class was generated from the following file: