rails_audit_log-graphql 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd228bcaff874e10bbd50927cb3bc44d22b5c860acf8dd444624eff80c7dea96
4
- data.tar.gz: 29ebf0ccd63fd0827689d3cf0b5e5bd3b4c6194c12468aa347c0fadb1fe0c5f3
3
+ metadata.gz: f64cce54638f8999c6489e0881a1fedfcb447b0b5b8f52270a0d8247719c8f19
4
+ data.tar.gz: 4b1225952a5a6adce3a5a03b804360765b0c70b9ad9a9688db96ba34139430c5
5
5
  SHA512:
6
- metadata.gz: 81930d3cedc11053354b5b86349d5483b326f43d774ebea49f97bc61e827c1ede95fa61c1b2671c611df266a9f7b4f4e497d472d47d86fc01b9e6863dd2b8df2
7
- data.tar.gz: 158775764845a120940581a0e6c47be8ca3ba992c5195b4bb899c970d069f27dc94faf53c4dde7ee1e4752992d8de62adec09f3f20a68e8209499239e9589887
6
+ metadata.gz: 0b54b242a022b49d1917dd3c0370f96bde5ec210dad8959a34bc424132c7efd97aa0e1f781cebd0eaf21056b3b29c2c0c9632c08e94a4b0e2da851afe57044e5
7
+ data.tar.gz: fb448e67961e641eb6ce89081e832082cfa886856ccbd5f4d5de767d1bd21835d38034e6dd55a4d00b1f633f58da6a094e5d8e4e4886c24a6aece095386023f2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.5.0] - 2026-06-04
4
+
5
+ ### Added
6
+
7
+ - `forTenant:` argument on `auditLogEntry`, `auditLogEntries`, and `auditLogEntriesConnection` — explicitly scope results to a tenant ID; overrides auto-tenant
8
+ - Auto-tenant scoping — when `RailsAuditLog.current_tenant` is configured, all queries automatically filter to the current tenant without requiring an explicit argument
9
+ - `auditLogEntriesCount(event:, itemType:, since:)` — new aggregation query returning the count of matching entries; respects auto-tenant
10
+
3
11
  ## [0.4.0] - 2026-06-04
4
12
 
5
13
  ### Added
data/README.md CHANGED
@@ -20,6 +20,8 @@ A [graphql-ruby](https://graphql-ruby.org) API layer for the [`rails_audit_log`]
20
20
  - [auditLogEntry](#auditlogentryid-id-auditlogentry)
21
21
  - [auditLogEntries](#auditlogentries-auditlogentry)
22
22
  - [auditLogEntriesConnection](#auditlogentriesconnection-auditlogentryconnection)
23
+ - [auditLogEntriesCount](#auditlogentriescount-int)
24
+ - [Tenant scoping](#tenant-scoping)
23
25
  - [Authentication](#authentication)
24
26
  - [Subscriptions](#subscriptions)
25
27
  - [AuditLogSubscriptionsMixin](#auditlogsubscriptionsmixin)
@@ -152,6 +154,7 @@ List entries with optional filters and offset pagination.
152
154
  | `until` | `ISO8601DateTime` | — | Return entries created at or before this time |
153
155
  | `touching` | `String` | — | Filter to entries that changed a specific attribute |
154
156
  | `orderBy` | `AuditLogEntrySortInput` | `CREATED_AT DESC` | Sort field and direction |
157
+ | `forTenant` | `String` | — | Scope to a specific tenant ID; overrides auto-tenant |
155
158
  | `page` | `Int` | `1` | Page number (1-based) |
156
159
  | `perPage` | `Int` | `25` | Results per page |
157
160
 
@@ -167,6 +170,7 @@ Same filters as `auditLogEntries`, but returns a [Relay-style connection](https:
167
170
  | `itemType` | `String` | Filter by audited model class name |
168
171
  | `itemId` | `ID` | Filter by audited record ID |
169
172
  | `actorId` | `ID` | Filter by actor ID |
173
+ | `forTenant` | `String` | Scope to a specific tenant ID; overrides auto-tenant |
170
174
  | `first` | `Int` | Return the first N edges after `after` |
171
175
  | `after` | `String` | Cursor to paginate forward from |
172
176
  | `last` | `Int` | Return the last N edges before `before` |
@@ -207,6 +211,40 @@ Results are ordered by `created_at DESC`.
207
211
 
208
212
  [↑ Back to top](#table-of-contents)
209
213
 
214
+ #### `auditLogEntriesCount(...): Int!`
215
+
216
+ Returns the count of matching audit log entries. Respects auto-tenant when `RailsAuditLog.current_tenant` is configured.
217
+
218
+ | Argument | Type | Description |
219
+ |---|---|---|
220
+ | `event` | `String` | Filter by event type (`create`, `update`, `destroy`) |
221
+ | `itemType` | `String` | Filter by audited model class name |
222
+ | `since` | `ISO8601DateTime` | Count entries created at or after this time |
223
+
224
+ ```graphql
225
+ { auditLogEntriesCount(event: "update", itemType: "Post") }
226
+ ```
227
+
228
+ [↑ Back to top](#table-of-contents)
229
+
230
+ #### Tenant scoping
231
+
232
+ When `RailsAuditLog.current_tenant` is configured, all queries automatically filter to the current tenant:
233
+
234
+ ```ruby
235
+ RailsAuditLog.configure do |c|
236
+ c.current_tenant { Current.tenant_id }
237
+ end
238
+ ```
239
+
240
+ To override or explicitly specify a tenant per query, use the `forTenant:` argument (available on `auditLogEntry`, `auditLogEntries`, and `auditLogEntriesConnection`):
241
+
242
+ ```graphql
243
+ { auditLogEntries(forTenant: "acme") { id event } }
244
+ ```
245
+
246
+ [↑ Back to top](#table-of-contents)
247
+
210
248
  ### Authentication
211
249
 
212
250
  If `RailsAuditLog.authenticate` is configured, the block is called with the GraphQL context before every query. Return a truthy value to allow access; return falsy to raise `GraphQL::ExecutionError` with `"Unauthorized"`.
data/ROADMAP.md CHANGED
@@ -4,14 +4,6 @@ This gem adds a GraphQL API layer on top of [`rails_audit_log`](https://github.c
4
4
 
5
5
  ---
6
6
 
7
- ## 0.5.0 — Multi-tenancy & Advanced Filtering
8
-
9
- - **Tenant scoping** — automatically scope queries via `RailsAuditLog.current_tenant` when configured
10
- - **`forTenant:` argument** — explicit tenant filter on `auditLogEntries`
11
- - **Aggregations** — `auditLogEntriesCount(event:, itemType:, since:)` for dashboard metrics
12
-
13
- ---
14
-
15
7
  ## 0.6.0 — Performance & Safety
16
8
 
17
9
  - **Dataloader batch loading** — batch-resolve polymorphic `actor` and `item` associations using graphql-ruby's `dataloader` to eliminate N+1 queries on list responses
@@ -14,6 +14,8 @@ module RailsAuditLog
14
14
  ) do
15
15
  argument :id, GraphQL::Types::ID, required: true,
16
16
  description: "ID of the audit log entry."
17
+ argument :for_tenant, String, required: false,
18
+ description: "Scope to a specific tenant ID. Overrides auto-tenant when RailsAuditLog.current_tenant is configured."
17
19
  end
18
20
 
19
21
  base.field(
@@ -31,6 +33,8 @@ module RailsAuditLog
31
33
  argument :until, GraphQL::Types::ISO8601DateTime, required: false, as: :until_time, description: "Return entries created at or before this time."
32
34
  argument :touching, String, required: false, description: "Filter to entries that changed a specific attribute (matches object_changes keys)."
33
35
  argument :order_by, RailsAuditLog::Graphql::InputObjects::AuditLogEntrySortInput, required: false, description: "Sort order. Defaults to CREATED_AT DESC."
36
+ argument :for_tenant, String, required: false,
37
+ description: "Scope to a specific tenant ID. Overrides auto-tenant when RailsAuditLog.current_tenant is configured."
34
38
  argument :page, GraphQL::Types::Int, required: false, default_value: 1, description: "Page number (1-based)."
35
39
  argument :per_page, GraphQL::Types::Int, required: false, default_value: 25, description: "Number of results per page."
36
40
  end
@@ -50,28 +54,55 @@ module RailsAuditLog
50
54
  argument :until, GraphQL::Types::ISO8601DateTime, required: false, as: :until_time, description: "Return entries created at or before this time."
51
55
  argument :touching, String, required: false, description: "Filter to entries that changed a specific attribute (matches object_changes keys)."
52
56
  argument :order_by, RailsAuditLog::Graphql::InputObjects::AuditLogEntrySortInput, required: false, description: "Sort order. Defaults to CREATED_AT DESC."
57
+ argument :for_tenant, String, required: false,
58
+ description: "Scope to a specific tenant ID. Overrides auto-tenant when RailsAuditLog.current_tenant is configured."
59
+ end
60
+
61
+ base.field(
62
+ :audit_log_entries_count,
63
+ GraphQL::Types::Int,
64
+ null: false,
65
+ description: "Count audit log entries with optional filters. Respects auto-tenant when RailsAuditLog.current_tenant is configured.",
66
+ resolver_method: :resolve_audit_log_entries_count
67
+ ) do
68
+ argument :event, String, required: false, description: "Filter by event type (create, update, destroy)."
69
+ argument :item_type, String, required: false, description: "Filter by audited model class name."
70
+ argument :since, GraphQL::Types::ISO8601DateTime, required: false, description: "Count entries created at or after this time."
53
71
  end
54
72
  end
55
73
 
56
- def resolve_audit_log_entry(id:)
74
+ def resolve_audit_log_entry(id:, for_tenant: nil)
57
75
  check_authentication!
58
- RailsAuditLog::AuditLogEntry.find_by(id: id)
76
+ tenant_id = for_tenant || RailsAuditLog.current_tenant&.call
77
+ base = tenant_id ? RailsAuditLog::AuditLogEntry.for_tenant(tenant_id) : RailsAuditLog::AuditLogEntry
78
+ base.find_by(id: id)
59
79
  end
60
80
 
61
- def resolve_audit_log_entries(event: nil, item_type: nil, item_id: nil, actor_id: nil, since: nil, until_time: nil, touching: nil, order_by: nil, page: 1, per_page: 25)
81
+ def resolve_audit_log_entries(event: nil, item_type: nil, item_id: nil, actor_id: nil, since: nil, until_time: nil, touching: nil, order_by: nil, for_tenant: nil, page: 1, per_page: 25)
62
82
  check_authentication!
63
- scope = build_scope(event: event, item_type: item_type, item_id: item_id, actor_id: actor_id, since: since, until_time: until_time, touching: touching, order_by: order_by)
83
+ scope = build_scope(event: event, item_type: item_type, item_id: item_id, actor_id: actor_id, since: since, until_time: until_time, touching: touching, order_by: order_by, for_tenant: for_tenant)
64
84
  scope.limit(per_page).offset((page - 1) * per_page)
65
85
  end
66
86
 
67
- def resolve_audit_log_entries_connection(event: nil, item_type: nil, item_id: nil, actor_id: nil, since: nil, until_time: nil, touching: nil, order_by: nil)
87
+ def resolve_audit_log_entries_connection(event: nil, item_type: nil, item_id: nil, actor_id: nil, since: nil, until_time: nil, touching: nil, order_by: nil, for_tenant: nil)
68
88
  check_authentication!
69
- build_scope(event: event, item_type: item_type, item_id: item_id, actor_id: actor_id, since: since, until_time: until_time, touching: touching, order_by: order_by)
89
+ build_scope(event: event, item_type: item_type, item_id: item_id, actor_id: actor_id, since: since, until_time: until_time, touching: touching, order_by: order_by, for_tenant: for_tenant)
90
+ end
91
+
92
+ def resolve_audit_log_entries_count(event: nil, item_type: nil, since: nil)
93
+ check_authentication!
94
+ scope = RailsAuditLog::AuditLogEntry.all
95
+ scope = scope.where(event: event) if event
96
+ scope = scope.where(item_type: item_type) if item_type
97
+ scope = scope.where("created_at >= ?", since) if since
98
+ tenant_id = RailsAuditLog.current_tenant&.call
99
+ scope = scope.for_tenant(tenant_id) if tenant_id
100
+ scope.count
70
101
  end
71
102
 
72
103
  private
73
104
 
74
- def build_scope(event: nil, item_type: nil, item_id: nil, actor_id: nil, since: nil, until_time: nil, touching: nil, order_by: nil)
105
+ def build_scope(event: nil, item_type: nil, item_id: nil, actor_id: nil, since: nil, until_time: nil, touching: nil, order_by: nil, for_tenant: nil)
75
106
  sort_field = order_by&.field || :created_at
76
107
  sort_direction = order_by&.direction || :desc
77
108
  scope = RailsAuditLog::AuditLogEntry.order(sort_field => sort_direction)
@@ -85,6 +116,8 @@ module RailsAuditLog
85
116
  safe = ActiveRecord::Base.sanitize_sql_like(touching)
86
117
  scope = scope.where("object_changes LIKE ?", "%\"#{safe}\":%")
87
118
  end
119
+ tenant_id = for_tenant || RailsAuditLog.current_tenant&.call
120
+ scope = scope.for_tenant(tenant_id) if tenant_id
88
121
  scope
89
122
  end
90
123
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RailsAuditLog
4
4
  module Graphql
5
- VERSION = "0.4.0"
5
+ VERSION = "0.5.0"
6
6
  end
7
7
  end
@@ -76,7 +76,7 @@ module RailsAuditLog
76
76
  module AuditLogEntriesQueryMixin
77
77
  def self.included: (untyped base) -> void
78
78
 
79
- def resolve_audit_log_entry: (id: String) -> untyped
79
+ def resolve_audit_log_entry: (id: String, ?for_tenant: String?) -> untyped
80
80
 
81
81
  def resolve_audit_log_entries: (
82
82
  ?event: String?,
@@ -87,6 +87,7 @@ module RailsAuditLog
87
87
  ?until_time: Time?,
88
88
  ?touching: String?,
89
89
  ?order_by: InputObjects::AuditLogEntrySortInput?,
90
+ ?for_tenant: String?,
90
91
  ?page: Integer,
91
92
  ?per_page: Integer
92
93
  ) -> untyped
@@ -99,9 +100,16 @@ module RailsAuditLog
99
100
  ?since: Time?,
100
101
  ?until_time: Time?,
101
102
  ?touching: String?,
102
- ?order_by: InputObjects::AuditLogEntrySortInput?
103
+ ?order_by: InputObjects::AuditLogEntrySortInput?,
104
+ ?for_tenant: String?
103
105
  ) -> untyped
104
106
 
107
+ def resolve_audit_log_entries_count: (
108
+ ?event: String?,
109
+ ?item_type: String?,
110
+ ?since: Time?
111
+ ) -> Integer
112
+
105
113
  private
106
114
 
107
115
  def build_scope: (
@@ -112,7 +120,8 @@ module RailsAuditLog
112
120
  ?since: Time?,
113
121
  ?until_time: Time?,
114
122
  ?touching: String?,
115
- ?order_by: InputObjects::AuditLogEntrySortInput?
123
+ ?order_by: InputObjects::AuditLogEntrySortInput?,
124
+ ?for_tenant: String?
116
125
  ) -> untyped
117
126
 
118
127
  def check_authentication!: () -> void
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_audit_log-graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chuck Smith