57const atna_coded_value kEventIdExport{
58 "110106",
"DCM",
"Export"};
59const atna_coded_value kEventIdImport{
60 "110107",
"DCM",
"Import"};
61const atna_coded_value kEventIdQuery{
62 "110112",
"DCM",
"Query"};
68const atna_coded_value kEventTypeIti18{
69 "urn:ihe:iti:2007:RegistryStoredQuery",
71 "Registry Stored Query"};
72const atna_coded_value kEventTypeIti41{
73 "ITI-41",
"IHETransactions",
74 "Provide and Register Document Set-b"};
75const atna_coded_value kEventTypeIti43{
76 "ITI-43",
"IHETransactions",
"Retrieve Document Set"};
79const atna_coded_value kXdsDocumentUniqueIdType{
80 "urn:ihe:iti:xds:2013:uniqueId",
"IHE XDS Metadata",
81 "XDSDocumentEntry.uniqueId"};
82const atna_coded_value kXdsEntryUuidType{
83 "urn:ihe:iti:xds:2013:entryUUID",
"IHE XDS Metadata",
84 "XDSDocumentEntry.entryUUID"};
85const atna_coded_value kXdsSubmissionSetUidType{
86 "urn:ihe:iti:xds:2013:submissionSet.uniqueId",
"IHE XDS Metadata",
87 "XDSSubmissionSet.uniqueId"};
93atna_active_participant make_participant(
const std::string& user_id,
95 const atna_coded_value& role) {
96 atna_active_participant p;
98 p.user_is_requestor = is_requestor;
100 p.role_id_codes.push_back(role);
104void attach_failure_detail(atna_audit_message& msg,
105 const std::string& description) {
106 if (description.empty())
return;
107 atna_object_detail d;
108 d.type =
"FailureDescription";
109 d.value = description;
110 if (msg.participant_objects.empty()) {
111 atna_participant_object synth;
114 synth.object_id_type_code = kXdsDocumentUniqueIdType;
115 synth.object_id =
"(no object context)";
116 synth.object_details.push_back(std::move(d));
117 msg.participant_objects.push_back(std::move(synth));
119 msg.participant_objects.back().object_details.push_back(std::move(d));
130 const std::string& audit_source_id,
const xds_iti41_event& e,
131 const std::string& local_participant_id) {
140 const std::string source =
141 local_participant_id.empty() ? e.source_id : local_participant_id;
147 if (!e.submission_set_unique_id.empty()) {
152 ss.
object_id = e.submission_set_unique_id;
155 for (
const auto&
uid : e.document_unique_ids) {
156 if (
uid.empty())
continue;
164 if (!e.patient_id.empty()) {
172 attach_failure_detail(msg, e.failure_description);
177 const std::string& audit_source_id,
const xds_iti43_event& e,
178 const std::string& local_participant_id) {
187 const std::string consumer =
188 local_participant_id.empty() ? e.consumer_id : local_participant_id;
197 if (!e.document_unique_id.empty()) {
205 if (!e.repository_unique_id.empty()) {
213 attach_failure_detail(msg, e.failure_description);
218 const std::string& audit_source_id,
const xds_iti18_event& e,
219 const std::string& local_participant_id) {
228 const std::string caller =
229 local_participant_id.empty() ? e.querier_id : local_participant_id;
235 if (e.query_kind == xds_iti18_event::kind::find_documents &&
236 !e.patient_id.empty()) {
244 for (
const auto& u : e.document_uuids) {
245 if (u.empty())
continue;
253 attach_failure_detail(msg, e.failure_description);
263class null_sink :
public xds_audit_sink {
265 void on_iti41_submit(
const xds_iti41_event&)
override {}
266 void on_iti43_retrieve(
const xds_iti43_event&)
override {}
267 void on_iti18_query(
const xds_iti18_event&)
override {}
270class atna_sink :
public xds_audit_sink {
272 atna_sink(atna_service_auditor& auditor, std::string local_participant_id)
276 void on_iti41_submit(
const xds_iti41_event& e)
override {
278 auditor_->audit_source_id(), e, local_participant_id_));
280 void on_iti43_retrieve(
const xds_iti43_event& e)
override {
282 auditor_->audit_source_id(), e, local_participant_id_));
284 void on_iti18_query(
const xds_iti18_event& e)
override {
286 auditor_->audit_source_id(), e, local_participant_id_));
301 return std::make_shared<null_sink>();
306 return std::make_shared<atna_sink>(auditor,
307 std::move(local_participant_id));
314void recording_xds_audit_sink::on_iti41_submit(
const xds_iti41_event& e) {
316 c.k = captured_event::kind::iti41;
318 events_.push_back(std::move(c));
321void recording_xds_audit_sink::on_iti43_retrieve(
const xds_iti43_event& e) {
323 c.k = captured_event::kind::iti43;
325 events_.push_back(std::move(c));
328void recording_xds_audit_sink::on_iti18_query(
const xds_iti18_event& e) {
330 c.k = captured_event::kind::iti18;
332 events_.push_back(std::move(c));
335const std::vector<recording_xds_audit_sink::captured_event>&
336recording_xds_audit_sink::events() const noexcept {
340void recording_xds_audit_sink::clear() noexcept {
High-level facade for ATNA audit logging in DICOM services.
High-level facade for emitting ATNA audit events from DICOM services.
@ move
C-MOVE move request/response.
const atna_coded_value node_id
Node ID.
const atna_coded_value patient_number
Patient Number (RFC 3881 defined)
const atna_coded_value source
Source Role ID (110153)
const atna_coded_value destination
Destination Role ID (110152)
atna_audit_message build_iti18_audit_message(const std::string &audit_source_id, const xds_iti18_event &e, const std::string &local_participant_id)
std::shared_ptr< xds_audit_sink > make_null_xds_audit_sink()
atna_audit_message build_iti41_audit_message(const std::string &audit_source_id, const xds_iti41_event &e, const std::string &local_participant_id)
std::shared_ptr< xds_audit_sink > make_atna_xds_audit_sink(atna_service_auditor &auditor, std::string local_participant_id)
atna_audit_message build_iti43_audit_message(const std::string &audit_source_id, const xds_iti43_event &e, const std::string &local_participant_id)
Complete RFC 3881 audit message.
atna_event_action event_action
Action that triggered the event.
std::vector< atna_participant_object > participant_objects
Participant objects (patients/studies/queries)
std::vector< atna_coded_value > event_type_codes
Event type codes for sub-classification.
atna_event_outcome event_outcome
Outcome of the event.
atna_coded_value event_id
Event ID coded value (e.g., DCM 110114 = UserAuthentication)
atna_audit_source audit_source
Audit source identification.
std::vector< atna_active_participant > active_participants
Active participants (users/processes)
std::chrono::system_clock::time_point event_date_time
When the event occurred.
std::string audit_source_id
Unique identifier for the audit source.
An object (patient, study, query) involved in the event.
std::string object_id
Object identifier (e.g., Patient ID, Study UID)
atna_object_role object_role
Role of the object in the event.
atna_object_type object_type
Object type.
atna_coded_value object_id_type_code
Object ID type code.
std::string local_participant_id_
atna_service_auditor * auditor_
ATNA audit event helpers for the IHE XDS.b actors (ITI-18/41/43).