From c67e3b774b8e0937958e6fe94b83ea34d57a0a7d Mon Sep 17 00:00:00 2001 From: Andrew Walker Date: Wed, 7 Aug 2024 12:39:36 -0700 Subject: [PATCH] Fix order_by when using raw sql queries on audit backend Order_by directives were not being applied to the generated SQL queryset that was being passed to the individual audit backend services. This wasn't caught because often filtering for generic audit queries happens via filter_list because the filters cannot be fully duplicated using native SQL features. --- .../middlewared/plugins/audit/backend.py | 2 ++ tests/api2/test_audit_basic.py | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/middlewared/middlewared/plugins/audit/backend.py b/src/middlewared/middlewared/plugins/audit/backend.py index 2a9793650a3f2..4ac0e2e0ac84e 100644 --- a/src/middlewared/middlewared/plugins/audit/backend.py +++ b/src/middlewared/middlewared/plugins/audit/backend.py @@ -218,6 +218,8 @@ def query(self, db_name, filters, options): if wrapper is not None: order_by[i] = wrapper(order_by[i]) + qs = qs.order_by(*order_by) + if options['offset']: qs = qs.offset(options['offset']) diff --git a/tests/api2/test_audit_basic.py b/tests/api2/test_audit_basic.py index 5c68b59efc010..a4a824edb4e80 100644 --- a/tests/api2/test_audit_basic.py +++ b/tests/api2/test_audit_basic.py @@ -215,6 +215,24 @@ def test_audit_query(self, initialize_for_smb_tests): retries -= 1 assert ops_count > initial_ops_count, f"retries remaining = {retries}" + def test_audit_order_by(self): + entries_forward = call('audit.query', {'services': ['SMB'], 'query-options': { + 'order_by': ['audit_id'] + }}) + + entries_reverse = call('audit.query', {'services': ['SMB'], 'query-options': { + 'order_by': ['-audit_id'] + }}) + + head_forward_id = entries_forward[0]['audit_id'] + tail_forward_id = entries_forward[-1]['audit_id'] + + head_reverse_id = entries_reverse[0]['audit_id'] + tail_reverse_id = entries_reverse[-1]['audit_id'] + + assert head_forward_id == tail_reverse_id + assert tail_forward_id == head_reverse_id + def test_audit_export(self): for backend in ['CSV', 'JSON', 'YAML']: report_path = call('audit.export', {'export_format': backend}, job=True)