rails_audit_log-graphql 0.6.0 → 0.6.1

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: 6ca2df96cd0a69c6449fc8585832293c9a06d487a7525f40c1d15762c61710b5
4
- data.tar.gz: 8262257281bef88c4ab07700ec88b5755ca6b2a095fd879bf5462d403ec1ac00
3
+ metadata.gz: a1df5ae47e9bae5cc635eb04372e8a84f3c484350f50284d98ab4602d9f2175c
4
+ data.tar.gz: 5bd2df5463caab8646bfab17973cd85343819b94fb189d6c3d52bbe65cbf11ce
5
5
  SHA512:
6
- metadata.gz: 4598525fe46095cbd1209e9bc3af297950526eb9c7ecfab9e382ee3554f376e73b0db3073986d49cdd05190e42f90e1d09e3f1a00c3ecb948a0f02d04f5ba9f0
7
- data.tar.gz: 2069e44509afdccf33c443bcf443da4480e83e60034f73bf24b0a7139ab012910d60e17dd85d06897b0642a6e4cb0d0d548a08c6bfbd5ac8318f6bd787d998b3
6
+ metadata.gz: 3899c333a5af6c7f9c1a05cfe1bc882f8464ad9da9d21ed677c75ce7ec6546a6181893d8a27f563822d46ed4bfb7d6f91e8349285d1bc83e3cc6aaae2a8d5147
7
+ data.tar.gz: cdc13b1d159a794f67fa1c46a3410b3196529dba59e234eba32147338d15e85a2478bcb676821738256792e4358100a4c07bc96cfb855c00d68db828807a1d48
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.6.1] - 2026-06-04
4
+
5
+ ### Added
6
+
7
+ - `actorType:` filter argument on `auditLogEntries`, `auditLogEntriesConnection`, and `auditLogEntriesCount` — filter by actor model class name (e.g. `"User"`)
8
+ - `forTenant:` argument on `auditLogReify` and `auditLogEntriesCount` — consistent tenant scoping across all query fields; both also respect `RailsAuditLog.current_tenant` auto-tenant
9
+
10
+ ### Changed
11
+
12
+ - `auditLogReify` return type changed from generic `JSON` to `AuditLogJson` for consistency with other entry fields
13
+ - `rails g rails_audit_log:graphql:install` now also injects `SchemaPlugin` into the host schema file (detected via `app/graphql/**/*schema*.rb` glob); `print_next_steps` updated to mention all available queries and the complexity config override
14
+
3
15
  ## [0.6.0] - 2026-06-04
4
16
 
5
17
  ### Added
data/README.md CHANGED
@@ -152,6 +152,7 @@ List entries with optional filters and offset pagination.
152
152
  | `itemType` | `String` | — | Filter by audited model class name |
153
153
  | `itemId` | `ID` | — | Filter by audited record ID |
154
154
  | `actorId` | `ID` | — | Filter by actor ID |
155
+ | `actorType` | `String` | — | Filter by actor model class name (e.g. `"User"`) |
155
156
  | `since` | `ISO8601DateTime` | — | Return entries created at or after this time |
156
157
  | `until` | `ISO8601DateTime` | — | Return entries created at or before this time |
157
158
  | `touching` | `String` | — | Filter to entries that changed a specific attribute |
@@ -172,6 +173,7 @@ Same filters as `auditLogEntries`, but returns a [Relay-style connection](https:
172
173
  | `itemType` | `String` | Filter by audited model class name |
173
174
  | `itemId` | `ID` | Filter by audited record ID |
174
175
  | `actorId` | `ID` | Filter by actor ID |
176
+ | `actorType` | `String` | Filter by actor model class name (e.g. `"User"`) |
175
177
  | `forTenant` | `String` | Scope to a specific tenant ID; overrides auto-tenant |
176
178
  | `first` | `Int` | Return the first N edges after `after` |
177
179
  | `after` | `String` | Cursor to paginate forward from |
@@ -221,7 +223,9 @@ Returns the count of matching audit log entries. Respects auto-tenant when `Rail
221
223
  |---|---|---|
222
224
  | `event` | `String` | Filter by event type (`create`, `update`, `destroy`) |
223
225
  | `itemType` | `String` | Filter by audited model class name |
226
+ | `actorType` | `String` | Filter by actor model class name (e.g. `"User"`) |
224
227
  | `since` | `ISO8601DateTime` | Count entries created at or after this time |
228
+ | `forTenant` | `String` | Scope to a specific tenant ID; overrides auto-tenant |
225
229
 
226
230
  ```graphql
227
231
  { auditLogEntriesCount(event: "update", itemType: "Post") }
@@ -291,9 +295,9 @@ The plugin also adds `AuditLogActor.record` and `AuditedResource.record` fields
291
295
 
292
296
  [↑ Back to top](#table-of-contents)
293
297
 
294
- ### `auditLogReify(itemType:, itemId:, at:): JSON`
298
+ ### `auditLogReify(itemType:, itemId:, at:): AuditLogJson`
295
299
 
296
- Reconstructs the attribute state of a record at a given point in time. Returns the attributes as JSON, or `nil` when no entry exists at or before `at` or the record was destroyed at that time.
300
+ Reconstructs the attribute state of a record at a given point in time. Returns the attributes as `AuditLogJson`, or `nil` when no entry exists at or before `at` or the record was destroyed at that time. Accepts `forTenant:` and respects auto-tenant.
297
301
 
298
302
  ```graphql
299
303
  {
@@ -7,10 +7,11 @@ module RailsAuditLog
7
7
  module Graphql
8
8
  class InstallGenerator < Rails::Generators::Base
9
9
  source_root File.expand_path("templates", __dir__)
10
- desc "Injects AuditLogEntriesQueryMixin into your GraphQL QueryType."
10
+ desc "Injects AuditLogEntriesQueryMixin into your GraphQL QueryType and SchemaPlugin into your schema."
11
11
 
12
12
  QUERY_TYPE_PATH = "app/graphql/types/query_type.rb"
13
13
  MIXIN = "RailsAuditLog::Graphql::Queries::AuditLogEntriesQueryMixin"
14
+ SCHEMA_PLUGIN = "RailsAuditLog::Graphql::SchemaPlugin"
14
15
 
15
16
  def inject_mixin
16
17
  if File.exist?(File.join(destination_root, QUERY_TYPE_PATH))
@@ -24,11 +25,31 @@ module RailsAuditLog
24
25
  end
25
26
  end
26
27
 
28
+ def inject_schema_plugin
29
+ schema_files = Dir.glob(File.join(destination_root, "app/graphql/**/*schema*.rb"))
30
+ if schema_files.any?
31
+ schema_path = schema_files.first.delete_prefix("#{destination_root}/")
32
+ inject_into_file schema_path,
33
+ " include #{SCHEMA_PLUGIN}\n",
34
+ after: /class\s+\S+\s*<\s*GraphQL::Schema\s*\n/
35
+ else
36
+ say ""
37
+ say "No schema file found. Add this line manually to your GraphQL::Schema subclass:", :yellow
38
+ say " include #{SCHEMA_PLUGIN}", :green
39
+ end
40
+ end
41
+
27
42
  def print_next_steps
28
43
  say ""
29
44
  say "Done! Your GraphQL API now has:", :green
30
45
  say " auditLogEntry(id: ID!): AuditLogEntry"
31
46
  say " auditLogEntries(...): [AuditLogEntry!]!"
47
+ say " auditLogReify(itemType:, itemId:, at:): AuditLogJson"
48
+ say " auditLogEntriesCount(...): Int!"
49
+ say ""
50
+ say "SchemaPlugin applies complexity/depth limits and enables dataloader."
51
+ say "Override defaults in an initializer:"
52
+ say " RailsAuditLog::Graphql.max_complexity = 500"
32
53
  say ""
33
54
  say "See the README for full documentation."
34
55
  end
@@ -29,6 +29,7 @@ module RailsAuditLog
29
29
  argument :item_type, String, required: false, description: "Filter by audited model class name."
30
30
  argument :item_id, GraphQL::Types::ID, required: false, description: "Filter by audited record ID."
31
31
  argument :actor_id, GraphQL::Types::ID, required: false, description: "Filter by actor ID."
32
+ argument :actor_type, String, required: false, description: "Filter by actor model class name (e.g. \"User\")."
32
33
  argument :since, GraphQL::Types::ISO8601DateTime, required: false, description: "Return entries created at or after this time."
33
34
  argument :until, GraphQL::Types::ISO8601DateTime, required: false, as: :until_time, description: "Return entries created at or before this time."
34
35
  argument :touching, String, required: false, description: "Filter to entries that changed a specific attribute (matches object_changes keys)."
@@ -50,6 +51,7 @@ module RailsAuditLog
50
51
  argument :item_type, String, required: false, description: "Filter by audited model class name."
51
52
  argument :item_id, GraphQL::Types::ID, required: false, description: "Filter by audited record ID."
52
53
  argument :actor_id, GraphQL::Types::ID, required: false, description: "Filter by actor ID."
54
+ argument :actor_type, String, required: false, description: "Filter by actor model class name (e.g. \"User\")."
53
55
  argument :since, GraphQL::Types::ISO8601DateTime, required: false, description: "Return entries created at or after this time."
54
56
  argument :until, GraphQL::Types::ISO8601DateTime, required: false, as: :until_time, description: "Return entries created at or before this time."
55
57
  argument :touching, String, required: false, description: "Filter to entries that changed a specific attribute (matches object_changes keys)."
@@ -60,7 +62,7 @@ module RailsAuditLog
60
62
 
61
63
  base.field(
62
64
  :audit_log_reify,
63
- GraphQL::Types::JSON,
65
+ Types::AuditLogJsonScalar,
64
66
  null: true,
65
67
  description: "Reconstruct the attribute state of a record at a given point in time. Returns nil when no entry exists at or before `at`, or when the record was destroyed.",
66
68
  resolver_method: :resolve_audit_log_reify
@@ -68,6 +70,8 @@ module RailsAuditLog
68
70
  argument :item_type, String, required: true, description: "The audited model class name."
69
71
  argument :item_id, GraphQL::Types::ID, required: true, description: "The audited record ID."
70
72
  argument :at, GraphQL::Types::ISO8601DateTime, required: true, description: "Reconstruct state as of this time."
73
+ argument :for_tenant, String, required: false,
74
+ description: "Scope to a specific tenant ID. Overrides auto-tenant when RailsAuditLog.current_tenant is configured."
71
75
  end
72
76
 
73
77
  base.field(
@@ -79,7 +83,10 @@ module RailsAuditLog
79
83
  ) do
80
84
  argument :event, String, required: false, description: "Filter by event type (create, update, destroy)."
81
85
  argument :item_type, String, required: false, description: "Filter by audited model class name."
86
+ argument :actor_type, String, required: false, description: "Filter by actor model class name (e.g. \"User\")."
82
87
  argument :since, GraphQL::Types::ISO8601DateTime, required: false, description: "Count entries created at or after this time."
88
+ argument :for_tenant, String, required: false,
89
+ description: "Scope to a specific tenant ID. Overrides auto-tenant when RailsAuditLog.current_tenant is configured."
83
90
  end
84
91
  end
85
92
 
@@ -90,43 +97,45 @@ module RailsAuditLog
90
97
  base.find_by(id: id)
91
98
  end
92
99
 
93
- 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)
100
+ def resolve_audit_log_entries(event: nil, item_type: nil, item_id: nil, actor_id: nil, actor_type: nil, since: nil, until_time: nil, touching: nil, order_by: nil, for_tenant: nil, page: 1, per_page: 25)
94
101
  check_authentication!
95
- 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)
102
+ scope = build_scope(event: event, item_type: item_type, item_id: item_id, actor_id: actor_id, actor_type: actor_type, since: since, until_time: until_time, touching: touching, order_by: order_by, for_tenant: for_tenant)
96
103
  scope.limit(per_page).offset((page - 1) * per_page)
97
104
  end
98
105
 
99
- 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)
106
+ def resolve_audit_log_entries_connection(event: nil, item_type: nil, item_id: nil, actor_id: nil, actor_type: nil, since: nil, until_time: nil, touching: nil, order_by: nil, for_tenant: nil)
100
107
  check_authentication!
101
- 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)
108
+ build_scope(event: event, item_type: item_type, item_id: item_id, actor_id: actor_id, actor_type: actor_type, since: since, until_time: until_time, touching: touching, order_by: order_by, for_tenant: for_tenant)
102
109
  end
103
110
 
104
- def resolve_audit_log_reify(item_type:, item_id:, at:)
111
+ def resolve_audit_log_reify(item_type:, item_id:, at:, for_tenant: nil)
105
112
  check_authentication!
106
- entry = RailsAuditLog::AuditLogEntry
113
+ tenant_id = for_tenant || RailsAuditLog.current_tenant&.call
114
+ scope = RailsAuditLog::AuditLogEntry
107
115
  .where(item_type: item_type, item_id: item_id)
108
116
  .where("created_at <= ?", at)
109
- .order(created_at: :desc, id: :desc)
110
- .first
117
+ scope = scope.for_tenant(tenant_id) if tenant_id
118
+ entry = scope.order(created_at: :desc, id: :desc).first
111
119
  return nil if entry.nil? || entry.event == "destroy"
112
120
  to_attrs = (entry.object_changes || {}).transform_values { |v| v[1] }
113
121
  entry.object.present? ? entry.object.merge(to_attrs) : to_attrs
114
122
  end
115
123
 
116
- def resolve_audit_log_entries_count(event: nil, item_type: nil, since: nil)
124
+ def resolve_audit_log_entries_count(event: nil, item_type: nil, actor_type: nil, since: nil, for_tenant: nil)
117
125
  check_authentication!
118
126
  scope = RailsAuditLog::AuditLogEntry.all
119
127
  scope = scope.where(event: event) if event
120
128
  scope = scope.where(item_type: item_type) if item_type
129
+ scope = scope.where(actor_type: actor_type) if actor_type
121
130
  scope = scope.where("created_at >= ?", since) if since
122
- tenant_id = RailsAuditLog.current_tenant&.call
131
+ tenant_id = for_tenant || RailsAuditLog.current_tenant&.call
123
132
  scope = scope.for_tenant(tenant_id) if tenant_id
124
133
  scope.count
125
134
  end
126
135
 
127
136
  private
128
137
 
129
- 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)
138
+ def build_scope(event: nil, item_type: nil, item_id: nil, actor_id: nil, actor_type: nil, since: nil, until_time: nil, touching: nil, order_by: nil, for_tenant: nil)
130
139
  sort_field = order_by&.field || :created_at
131
140
  sort_direction = order_by&.direction || :desc
132
141
  scope = RailsAuditLog::AuditLogEntry.order(sort_field => sort_direction)
@@ -134,6 +143,7 @@ module RailsAuditLog
134
143
  scope = scope.where(item_type: item_type) if item_type
135
144
  scope = scope.where(item_id: item_id) if item_id
136
145
  scope = scope.where(actor_id: actor_id) if actor_id
146
+ scope = scope.where(actor_type: actor_type) if actor_type
137
147
  scope = scope.where("created_at >= ?", since) if since
138
148
  scope = scope.where("created_at <= ?", until_time) if until_time
139
149
  if touching
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RailsAuditLog
4
4
  module Graphql
5
- VERSION = "0.6.0"
5
+ VERSION = "0.6.1"
6
6
  end
7
7
  end
@@ -112,6 +112,7 @@ module RailsAuditLog
112
112
  ?item_type: String?,
113
113
  ?item_id: String?,
114
114
  ?actor_id: String?,
115
+ ?actor_type: String?,
115
116
  ?since: Time?,
116
117
  ?until_time: Time?,
117
118
  ?touching: String?,
@@ -126,6 +127,7 @@ module RailsAuditLog
126
127
  ?item_type: String?,
127
128
  ?item_id: String?,
128
129
  ?actor_id: String?,
130
+ ?actor_type: String?,
129
131
  ?since: Time?,
130
132
  ?until_time: Time?,
131
133
  ?touching: String?,
@@ -136,13 +138,16 @@ module RailsAuditLog
136
138
  def resolve_audit_log_reify: (
137
139
  item_type: String,
138
140
  item_id: String,
139
- at: Time
141
+ at: Time,
142
+ ?for_tenant: String?
140
143
  ) -> Hash[String, untyped]?
141
144
 
142
145
  def resolve_audit_log_entries_count: (
143
146
  ?event: String?,
144
147
  ?item_type: String?,
145
- ?since: Time?
148
+ ?actor_type: String?,
149
+ ?since: Time?,
150
+ ?for_tenant: String?
146
151
  ) -> Integer
147
152
 
148
153
  private
@@ -152,6 +157,7 @@ module RailsAuditLog
152
157
  ?item_type: String?,
153
158
  ?item_id: String?,
154
159
  ?actor_id: String?,
160
+ ?actor_type: String?,
155
161
  ?since: Time?,
156
162
  ?until_time: Time?,
157
163
  ?touching: String?,
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.6.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chuck Smith