rails_audit_log-graphql 0.1.0 → 0.2.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 +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +48 -0
- data/ROADMAP.md +0 -9
- data/Rakefile +2 -0
- data/lib/rails_audit_log/graphql/input_objects/audit_log_entry_sort_input.rb +15 -0
- data/lib/rails_audit_log/graphql/queries/audit_log_entries_query_mixin.rb +44 -5
- data/lib/rails_audit_log/graphql/types/audit_log_entry_sort_field_enum.rb +14 -0
- data/lib/rails_audit_log/graphql/types/sort_direction_enum.rb +15 -0
- data/lib/rails_audit_log/graphql/version.rb +1 -1
- data/lib/rails_audit_log/graphql.rb +3 -0
- data/sig/rails_audit_log/graphql.rbs +52 -2
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6c89d640d69c533ded27f477ed99b03275c34b4564c90e6eaccfe86a131f2447
|
|
4
|
+
data.tar.gz: d34b732d907a2db6b9c6c0bfba266933aaf6f21be9c8770caa8c64b50a81c870
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: faa1b363d2aaebc1b3f5573f0b6c757a5d6b4d1fe8b6a1af7d906bd9877f23cecf897b75640b9f61e24e622d06c4233825be5047bada0d92371f954749a2499f
|
|
7
|
+
data.tar.gz: '08c32d0f02192b6db82d11e414ac04beb42a54ce61bb6dd8b025b2866f1569bc65b7b177ba308a4c0d241d7486029741e03abf082af38726fa2bbd30d6d2c6f4'
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.2.0] - 2026-06-03
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `auditLogEntriesConnection` — new Relay-style cursor-paginated field returning `AuditLogEntryConnection!` with `nodes`, `edges`, `pageInfo`, and `first`/`after`/`last`/`before` arguments; accepts the same filters as `auditLogEntries`
|
|
8
|
+
- `since:` and `until:` (`ISO8601DateTime`) arguments on both `auditLogEntries` and `auditLogEntriesConnection` for filtering by creation time range
|
|
9
|
+
- `touching:` (`String`) argument on both `auditLogEntries` and `auditLogEntriesConnection` — filters to entries whose `object_changes` include the named attribute
|
|
10
|
+
- `orderBy:` (`AuditLogEntrySortInput`) argument on both `auditLogEntries` and `auditLogEntriesConnection` — accepts `{ field: CREATED_AT, direction: ASC | DESC }`; defaults to `CREATED_AT DESC`
|
|
11
|
+
- `AuditLogEntrySortInput` input object type, `AuditLogEntrySortField` enum, and `SortDirection` enum added to the schema
|
|
12
|
+
|
|
3
13
|
## [0.1.0] - 2026-06-03
|
|
4
14
|
|
|
5
15
|
### Added
|
data/README.md
CHANGED
|
@@ -94,6 +94,54 @@ List entries with optional filters and offset pagination.
|
|
|
94
94
|
|
|
95
95
|
Results are ordered by `created_at DESC`.
|
|
96
96
|
|
|
97
|
+
#### `auditLogEntriesConnection(...): AuditLogEntryConnection!`
|
|
98
|
+
|
|
99
|
+
Same filters as `auditLogEntries`, but returns a [Relay-style connection](https://relay.dev/graphql/connections.htm) for cursor-based pagination.
|
|
100
|
+
|
|
101
|
+
| Argument | Type | Description |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `event` | `String` | Filter by event type (`create`, `update`, `destroy`) |
|
|
104
|
+
| `itemType` | `String` | Filter by audited model class name |
|
|
105
|
+
| `itemId` | `ID` | Filter by audited record ID |
|
|
106
|
+
| `actorId` | `ID` | Filter by actor ID |
|
|
107
|
+
| `first` | `Int` | Return the first N edges after `after` |
|
|
108
|
+
| `after` | `String` | Cursor to paginate forward from |
|
|
109
|
+
| `last` | `Int` | Return the last N edges before `before` |
|
|
110
|
+
| `before` | `String` | Cursor to paginate backward from |
|
|
111
|
+
|
|
112
|
+
Results are ordered by `created_at DESC`.
|
|
113
|
+
|
|
114
|
+
**Example — first page:**
|
|
115
|
+
|
|
116
|
+
```graphql
|
|
117
|
+
{
|
|
118
|
+
auditLogEntriesConnection(first: 25) {
|
|
119
|
+
nodes {
|
|
120
|
+
id
|
|
121
|
+
event
|
|
122
|
+
itemType
|
|
123
|
+
itemId
|
|
124
|
+
createdAt
|
|
125
|
+
}
|
|
126
|
+
pageInfo {
|
|
127
|
+
hasNextPage
|
|
128
|
+
endCursor
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Example — next page using a cursor:**
|
|
135
|
+
|
|
136
|
+
```graphql
|
|
137
|
+
{
|
|
138
|
+
auditLogEntriesConnection(first: 25, after: "eyJpZCI6NDJ9") {
|
|
139
|
+
nodes { id event }
|
|
140
|
+
pageInfo { hasNextPage endCursor }
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
97
145
|
[↑ Back to top](#table-of-contents)
|
|
98
146
|
|
|
99
147
|
### Authentication
|
data/ROADMAP.md
CHANGED
|
@@ -4,15 +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.2.0 — Filtering & Connections
|
|
8
|
-
|
|
9
|
-
- **Time-range filters** — `since:` and `until:` arguments on `auditLogEntries`
|
|
10
|
-
- **`touching:` filter** — narrow results to entries that changed a specific attribute
|
|
11
|
-
- **Relay-style connection** — replace offset pagination with cursor-based `AuditLogEntryConnection` for forward/backward pagination
|
|
12
|
-
- **Sorting** — `orderBy: { field: CREATED_AT, direction: DESC }`
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
7
|
## 0.3.0 — Actor & Resource Resolver Types
|
|
17
8
|
|
|
18
9
|
- **`ActorType`** — resolve the polymorphic `actor` to the concrete type in the host app's schema (requires a configurable type resolver proc)
|
data/Rakefile
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RailsAuditLog
|
|
4
|
+
module Graphql
|
|
5
|
+
module InputObjects
|
|
6
|
+
class AuditLogEntrySortInput < GraphQL::Schema::InputObject
|
|
7
|
+
graphql_name "AuditLogEntrySortInput"
|
|
8
|
+
description "Sort order for audit log entry queries."
|
|
9
|
+
|
|
10
|
+
argument :field, Types::AuditLogEntrySortFieldEnum, required: true, description: "Field to sort by."
|
|
11
|
+
argument :direction, Types::SortDirectionEnum, required: true, description: "Sort direction (ASC or DESC)."
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -27,9 +27,30 @@ module RailsAuditLog
|
|
|
27
27
|
argument :item_type, String, required: false, description: "Filter by audited model class name."
|
|
28
28
|
argument :item_id, GraphQL::Types::ID, required: false, description: "Filter by audited record ID."
|
|
29
29
|
argument :actor_id, GraphQL::Types::ID, required: false, description: "Filter by actor ID."
|
|
30
|
+
argument :since, GraphQL::Types::ISO8601DateTime, required: false, description: "Return entries created at or after this time."
|
|
31
|
+
argument :until, GraphQL::Types::ISO8601DateTime, required: false, as: :until_time, description: "Return entries created at or before this time."
|
|
32
|
+
argument :touching, String, required: false, description: "Filter to entries that changed a specific attribute (matches object_changes keys)."
|
|
33
|
+
argument :order_by, RailsAuditLog::Graphql::InputObjects::AuditLogEntrySortInput, required: false, description: "Sort order. Defaults to CREATED_AT DESC."
|
|
30
34
|
argument :page, GraphQL::Types::Int, required: false, default_value: 1, description: "Page number (1-based)."
|
|
31
35
|
argument :per_page, GraphQL::Types::Int, required: false, default_value: 25, description: "Number of results per page."
|
|
32
36
|
end
|
|
37
|
+
|
|
38
|
+
base.field(
|
|
39
|
+
:audit_log_entries_connection,
|
|
40
|
+
RailsAuditLog::Graphql::Types::AuditLogEntryType.connection_type,
|
|
41
|
+
null: false,
|
|
42
|
+
description: "List audit log entries with optional filters. Cursor-paginated (Relay connection).",
|
|
43
|
+
resolver_method: :resolve_audit_log_entries_connection
|
|
44
|
+
) do
|
|
45
|
+
argument :event, String, required: false, description: "Filter by event type (create, update, destroy)."
|
|
46
|
+
argument :item_type, String, required: false, description: "Filter by audited model class name."
|
|
47
|
+
argument :item_id, GraphQL::Types::ID, required: false, description: "Filter by audited record ID."
|
|
48
|
+
argument :actor_id, GraphQL::Types::ID, required: false, description: "Filter by actor ID."
|
|
49
|
+
argument :since, GraphQL::Types::ISO8601DateTime, required: false, description: "Return entries created at or after this time."
|
|
50
|
+
argument :until, GraphQL::Types::ISO8601DateTime, required: false, as: :until_time, description: "Return entries created at or before this time."
|
|
51
|
+
argument :touching, String, required: false, description: "Filter to entries that changed a specific attribute (matches object_changes keys)."
|
|
52
|
+
argument :order_by, RailsAuditLog::Graphql::InputObjects::AuditLogEntrySortInput, required: false, description: "Sort order. Defaults to CREATED_AT DESC."
|
|
53
|
+
end
|
|
33
54
|
end
|
|
34
55
|
|
|
35
56
|
def resolve_audit_log_entry(id:)
|
|
@@ -37,18 +58,36 @@ module RailsAuditLog
|
|
|
37
58
|
RailsAuditLog::AuditLogEntry.find_by(id: id)
|
|
38
59
|
end
|
|
39
60
|
|
|
40
|
-
def resolve_audit_log_entries(event: nil, item_type: nil, item_id: nil, actor_id: nil, page: 1, per_page: 25)
|
|
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)
|
|
41
62
|
check_authentication!
|
|
42
|
-
scope =
|
|
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)
|
|
64
|
+
scope.limit(per_page).offset((page - 1) * per_page)
|
|
65
|
+
end
|
|
66
|
+
|
|
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)
|
|
68
|
+
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)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
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)
|
|
75
|
+
sort_field = order_by&.field || :created_at
|
|
76
|
+
sort_direction = order_by&.direction || :desc
|
|
77
|
+
scope = RailsAuditLog::AuditLogEntry.order(sort_field => sort_direction)
|
|
43
78
|
scope = scope.where(event: event) if event
|
|
44
79
|
scope = scope.where(item_type: item_type) if item_type
|
|
45
80
|
scope = scope.where(item_id: item_id) if item_id
|
|
46
81
|
scope = scope.where(actor_id: actor_id) if actor_id
|
|
47
|
-
scope.
|
|
82
|
+
scope = scope.where("created_at >= ?", since) if since
|
|
83
|
+
scope = scope.where("created_at <= ?", until_time) if until_time
|
|
84
|
+
if touching
|
|
85
|
+
safe = ActiveRecord::Base.sanitize_sql_like(touching)
|
|
86
|
+
scope = scope.where("object_changes LIKE ?", "%\"#{safe}\":%")
|
|
87
|
+
end
|
|
88
|
+
scope
|
|
48
89
|
end
|
|
49
90
|
|
|
50
|
-
private
|
|
51
|
-
|
|
52
91
|
def check_authentication!
|
|
53
92
|
auth = RailsAuditLog.authenticate
|
|
54
93
|
return unless auth
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RailsAuditLog
|
|
4
|
+
module Graphql
|
|
5
|
+
module Types
|
|
6
|
+
class AuditLogEntrySortFieldEnum < GraphQL::Schema::Enum
|
|
7
|
+
graphql_name "AuditLogEntrySortField"
|
|
8
|
+
description "Fields available for sorting audit log entries."
|
|
9
|
+
|
|
10
|
+
value "CREATED_AT", value: :created_at, description: "Sort by creation time."
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RailsAuditLog
|
|
4
|
+
module Graphql
|
|
5
|
+
module Types
|
|
6
|
+
class SortDirectionEnum < GraphQL::Schema::Enum
|
|
7
|
+
graphql_name "SortDirection"
|
|
8
|
+
description "Sort direction for ordered queries."
|
|
9
|
+
|
|
10
|
+
value "ASC", value: :asc, description: "Ascending order."
|
|
11
|
+
value "DESC", value: :desc, description: "Descending order."
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -4,6 +4,9 @@ require "graphql"
|
|
|
4
4
|
require_relative "graphql/version"
|
|
5
5
|
require_relative "graphql/types/base_object"
|
|
6
6
|
require_relative "graphql/types/audit_log_entry_type"
|
|
7
|
+
require_relative "graphql/types/sort_direction_enum"
|
|
8
|
+
require_relative "graphql/types/audit_log_entry_sort_field_enum"
|
|
9
|
+
require_relative "graphql/input_objects/audit_log_entry_sort_input"
|
|
7
10
|
require_relative "graphql/queries/audit_log_entries_query_mixin"
|
|
8
11
|
|
|
9
12
|
module RailsAuditLog
|
|
@@ -8,6 +8,19 @@ module RailsAuditLog
|
|
|
8
8
|
|
|
9
9
|
class AuditLogEntryType < BaseObject
|
|
10
10
|
end
|
|
11
|
+
|
|
12
|
+
class SortDirectionEnum < GraphQL::Schema::Enum
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class AuditLogEntrySortFieldEnum < GraphQL::Schema::Enum
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
module InputObjects
|
|
20
|
+
class AuditLogEntrySortInput < GraphQL::Schema::InputObject
|
|
21
|
+
def field: () -> Symbol
|
|
22
|
+
def direction: () -> Symbol
|
|
23
|
+
end
|
|
11
24
|
end
|
|
12
25
|
|
|
13
26
|
module Generators
|
|
@@ -22,11 +35,48 @@ module RailsAuditLog
|
|
|
22
35
|
module Queries
|
|
23
36
|
module AuditLogEntriesQueryMixin
|
|
24
37
|
def self.included: (untyped base) -> void
|
|
38
|
+
|
|
25
39
|
def resolve_audit_log_entry: (id: String) -> untyped
|
|
26
|
-
|
|
40
|
+
|
|
41
|
+
def resolve_audit_log_entries: (
|
|
42
|
+
?event: String?,
|
|
43
|
+
?item_type: String?,
|
|
44
|
+
?item_id: String?,
|
|
45
|
+
?actor_id: String?,
|
|
46
|
+
?since: Time?,
|
|
47
|
+
?until_time: Time?,
|
|
48
|
+
?touching: String?,
|
|
49
|
+
?order_by: InputObjects::AuditLogEntrySortInput?,
|
|
50
|
+
?page: Integer,
|
|
51
|
+
?per_page: Integer
|
|
52
|
+
) -> untyped
|
|
53
|
+
|
|
54
|
+
def resolve_audit_log_entries_connection: (
|
|
55
|
+
?event: String?,
|
|
56
|
+
?item_type: String?,
|
|
57
|
+
?item_id: String?,
|
|
58
|
+
?actor_id: String?,
|
|
59
|
+
?since: Time?,
|
|
60
|
+
?until_time: Time?,
|
|
61
|
+
?touching: String?,
|
|
62
|
+
?order_by: InputObjects::AuditLogEntrySortInput?
|
|
63
|
+
) -> untyped
|
|
64
|
+
|
|
27
65
|
private
|
|
66
|
+
|
|
67
|
+
def build_scope: (
|
|
68
|
+
?event: String?,
|
|
69
|
+
?item_type: String?,
|
|
70
|
+
?item_id: String?,
|
|
71
|
+
?actor_id: String?,
|
|
72
|
+
?since: Time?,
|
|
73
|
+
?until_time: Time?,
|
|
74
|
+
?touching: String?,
|
|
75
|
+
?order_by: InputObjects::AuditLogEntrySortInput?
|
|
76
|
+
) -> untyped
|
|
77
|
+
|
|
28
78
|
def check_authentication!: () -> void
|
|
29
79
|
end
|
|
30
80
|
end
|
|
31
81
|
end
|
|
32
|
-
end
|
|
82
|
+
end
|
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
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chuck Smith
|
|
@@ -83,10 +83,13 @@ files:
|
|
|
83
83
|
- codecov.yml
|
|
84
84
|
- lib/generators/rails_audit_log/graphql/install/install_generator.rb
|
|
85
85
|
- lib/rails_audit_log/graphql.rb
|
|
86
|
+
- lib/rails_audit_log/graphql/input_objects/audit_log_entry_sort_input.rb
|
|
86
87
|
- lib/rails_audit_log/graphql/queries/audit_log_entries_query_mixin.rb
|
|
87
88
|
- lib/rails_audit_log/graphql/release_tooling.rb
|
|
89
|
+
- lib/rails_audit_log/graphql/types/audit_log_entry_sort_field_enum.rb
|
|
88
90
|
- lib/rails_audit_log/graphql/types/audit_log_entry_type.rb
|
|
89
91
|
- lib/rails_audit_log/graphql/types/base_object.rb
|
|
92
|
+
- lib/rails_audit_log/graphql/types/sort_direction_enum.rb
|
|
90
93
|
- lib/rails_audit_log/graphql/version.rb
|
|
91
94
|
- sig/rails_audit_log/graphql.rbs
|
|
92
95
|
homepage: https://github.com/eclectic-coding/rails_audit_log-graphql
|