- OperationStore: Add forward compatibility for removing old validation code #5164
- OperationStore: Improve
syncperformance withGraphQL::Schema::Visibility
- Subscriptions: show broadcast subscriber count in dashboard (Pusher requires "subscription count" to be turned on and
use ... show_broadcast_subscribers_count: true)
- OperationStore: Accept a
context:in#add
- Subscriptions: use a single Pusher or Ably channel to deliver broadcast payloads to subscribers
- Dashboard: fix crash when a topic had no active subscriptions
- Subscriptions: Track
last_triggered_at; add more metadata to the dashboard.
- OperationStore: require the
ActiveRecordbackend inside anActiveSupport.on_load(:active_record) { ... }block to improve Rails compatibility
- Subscriptions: Fix another Lua error in big cleanup operations
- Subscriptions: Fix Lua error when cleaning up huge numbers of inactive subscriptions
- OperationStore: remove needless call to
.metadata#4947
- Pundit, CanCan, OperationStore: add Rails generators for getting started
- OperationStore: Fix
.reindexfor many stored operations #4940
- Dashboard: handle missing index references gracefully #4940
- OperationStore: Don't call
query.query_stringif there's already a parsed document #4922
- RelationConnection: support Arel's
NullsFirstandNullsLastnodes #4910
- OperationStore::AddOperationBatch: remove rescue for StatementInvalid inside transaction
- RelationConnection: Don't quote table names that weren't quoted in original SQL, fixes #4508 (comment)
- OperationStore: fix
syncendpoint for Rack 3+ #4829 - Improve error message handling on Rails 7.1
@defer/@stream: Write delimiters at the end of each patch so that clients respond to payloads more quickly. (Previously, delimiters were added at the start of each patch, so clients had to wait for the next patch before they knew the current one was complete.)
- Pundit integration: improve error message when a
Scopeclass is missing
-
Pundit integration: when the integration encounters an Array, it tries to find a configured policy class. If it can't, it raises an error.
Previously, the integration silently permitted all items in the array; this default has been changed. See #4726 for more discussion of this change.
If you encounter this error:
- add
scope: falseto any fields that return arrays to get the previous behavior (no authorization applied to the array; each item authorized on its own) - Or, apply scoping by manually configuring a
pundit_policy_classin the field's return type, then adding aclass Scope ...inside that policy class. See the Pundit docs for the scope class API: https://github.com/varvet/pundit#scopes.
If you want to continue passing all arrays through without scoping (for example, if you know they've already been authorized another way, or if you're OK with them being authorized one-at-a-time later), you can implement this in your base
Scopeclass, for example:class BasePolicy class Scope def initialize(user, items) @user = user @items = items end def resolve if items.is_a?(Array) items else raise "Implement #{self.class}#resolve to filter these items: #{items.inspect}" end end end # Pass this scope class along to subclasses: def self.inherited(child_class) child_class.const_set(:Scope, Class.new(BasePolicy::Scope)) super end end
Alternatively, you could implement
def self.scope_items(items, context)to skip arrays, for example:module SkipScopingOnArrays def scope_items(items, context) if items.is_a?(Array) items # return these as-is else super end end end # Then, in type definitions which should skip scoping on arrays: extend SkipScopingOnArrays
- add
- Subscriptions: send
more: falsewhen the server callsunsubscribe
- Ably subscriptions: update webhook handler for
presence.messageevents
- OperationStore:
.dupthe givencontextto avoid leaking state between queries when indexing - Subscriptions: use the schema or query logger to output debug messages
- OperationStore: don't sort directives when normalizing, properly retain directives on Operation and Fragment definitions #4703
- OperationStore: also pass
context:for ActiveRecord backend batches
- OperationStore: accept
context:forAddOperationBatch.call#4697
- OperationStore: accept
context:toValidate.validate#4697
- OperationStore: don't rescue application-raised
KeyErrors #4699
- OperationStore: fix compatibility with 1.12.x #4696
- Improve compatibility with GraphQL-Ruby 1.12.x
- OperationStore: Preserve variable default values of
falsewhen normalizing queries
- OperationStore: search for operation during
Query#initializeto avoid races with other instrumentation. Adduse ... trace: trueto get the old behavior.
- Stable relation connections: quote table names and column names in
WHEREclauses #4508
- Defer: Add
incremental: truefor new proposed wire format, add example for working with GraphQL-Batch #4477
- Stable relation connection: Quote table names and column names in selects and orders #4485
@defer: updatecontext[:current_path]usage to fixpath:on deferred errors
OperationStore: fix when used with Changesets (or other ways of defining arguments with the same name) #4440
- Remove debug output, oops
- Fix
OperationStorewith new module-based execution traces (#4389)
- Support the
redis-clientgem asredis:
- Dashboard: Support Ruby 3.2.0
- OperationStore: Support
Changeset-Versionheader for syncing with changesets #4304
- Stable Relation Connections: Fix handling of Postgres JSON accesses
- Subscriptions: accept
connection_pool:instead ofredis:for use with theconnection_poolgem
- Stable connections: rescue
ActiveRecord::StatementInvalidwhen loading nodes and return a client-facing error instead
- Ably subscriptions: Also listen for
presence.leavewebhooks to clean up subscriptions more quickly
- Dashboard: nicely render subscriptions that are not found or cleaned up by
read_subscription_failed_error
- Add
GraphQL::Pro::Subscriptions#read_subscription_failed_errorfor handling errors that are raised when reloading queries from storage
- Add dashboard component for Enterprise mutation limiter
- Redis: update redis usage to be forward-compatible with redis 5.x #4167
- Stable connections: support SQL queries that sort by
IS NOT NULL#4153
- Stable connections: handle
edges {...}when an invalid cursor is given #4148
- Use
deprecated_accepts_definitionsto stop warnings when loading this gem on 1.13.x
- Pusher subscriptions: don't try to send empty trigger batches to Pusher
- Pusher subscriptions: it now sends updates in groups of 10 by default, pass
use ..., batch_size: 1to revert to the previous behavior. - OperationStore: when using ActiveRecord for storage, it now batches updates to
last_used_atevery 5 seconds. Passuse ..., update_last_used_at_every: 0to update that column synchronously, instead, as before.
- OperationStore: Fix no method error in Redis pipeline usage
- Postgres stable connection: support more complex aliased selects #3976
- Encoders: don't extend
DeprecatedDefineif it's not present (graphql-ruby < 1.12)
- Future-proof for GraphQL-Ruby 2.0
- Dashboard, Routes: support lazy-loading the schema with
Routes::Lazy#3868 - OperationStore: Update deprecated usage of
@redis.pipelinedto address warning
- Stream, Defer: Include
hasNext: true|falsein patches
- Stream: Add
@streamdirective for evaluating list items one-at-a-time
- Stable connections: Fix using startCursor / endCursor without nodes #3752
- Stable Connections: Properly handle cursors containing invalid JSON #3735
- Operation Store sync: ActiveRecord backend performance improvements: when syncing operations, only validate newly-added operations, reduce allocations when normalizing incoming query strings
- Operation Store sync: fix when operations are re-synced with new aliases
- Operation Store: Use Rails
insert_allfor better performance when adding new operations
- Pundit and CanCan integrations: Add
ResolverIntegrationmodules for plain resolvers #3392
- OperationStore Redis backend: pipeline updates to last_used_at values #3672
- OperationStore: fix a stack overflow error on GraphQL 1.9 #3653
- Dashboard: add a component for GraphQL-Enterprise rate limiters
- Stable cursors: raise an error on unrecognized orderings instead of ignoring them #3605
- Stable cursors: Handle
Arel::Attributes::AttributeandArel::SqlLiteral#3605
- Stable connections: nicely handle incoming cursors with too many sort values #3581
- Stable connections: improve handling of
SELECTwithCASE#3558 - Defer: fix to support runtime wrapper objects in graphql-ruby 1.12.13
- Ably subscriptions: send
quickAck: truefor a faster response from Ably
- Defer: support dataloader inside deferred blocks
- Defer: support
label:argument which is returned in the patch for that deferral #3454
- Dashboard: fix stack error when OperationStore isn't configured on a class-based schema
- Stable Connections: When using aliases and GROUP BY, replace the alias when building a HAVING condition.
- Pundit integration: Add a
use_owner_role(true)configuration option
- Stable Connections: Re-select aliased fields that are referenced by ORDER BY. #3421
- Pundit integration: properly halt when
unauthorized_by_punditreturns errors-as-data after a mutation argument fails authorization #3384
- Pundit, CanCan integrations: properly call configured auth hooks for arguments that are lists and input objects
- Fix OperationStore assignment on GraphQL-Ruby 1.9
- Subscriptions: change the default
cleanup_delay_s:to 5 seconds (usecleanup_delay_s: 0to get the old behavior)
- Subscriptions: Handle unsubscribe race condition #3357
- CanCan integration: support
can_can_subject:config for overriding the use ofobjectas the CanCan subject #3350
- Subscriptions: Support
Redis::Namespacewithout deprecation warnings forscript load#3347
- Stable connections: implement
range_add_edgeto leverage GraphQL-Ruby 1.12.5's improved RangeAdd #2184
- Defer: Update to work with Dataloader
- Subscriptions: Use
MULTIinstead of Lua for some operations - Subscriptions: Use
EVAL_SHAfor duplicate scripts to reduce network overhead #3285 - Subscriptions: Don't use
redis.call, which is unsupported in theredis-namespacegem #3322
- Stable Relation Connection: Don't emit
OR ... IS NULLfor columns that are known to benull: false(this improves index utilization)
- Pusher subscriptions:
context[:compress_pusher_payload] = truewill cause the payload to be gzipped before being sent to Pusher
- Subscriptions: don't generate keys inside Lua scripts (for redis-namespace compatibility, and probably better support for Redis cluster) #3307
- OperationStore: add
OperationStore::AddOperationBatch.callfor adding data directly - Subscriptions: use Lua scripts for more efficient Redis access
- Updates for 1.12.0 compatibility
- OperationStore: improve performance by batching reads and writes during updates
- Subscriptions: Add
stale_ttl_s:andcleanup_delay_s:to customize persistence in Redis #3252
- Fix duplicate calls to
Argument#authorized?in CanCan and Pundit integrations #3242
- Ably Subscriptions:
cipher_base:sets up end-to-end encryption
- Encoder: fix Ruby 2.7 warning #3161
- Stable connections: Handle
ARRAY[...]selections and cursors on Postgres #3166 - Pundit: properly lookup policies for list inputs #3146
- Stable Connections: Use method access to get
.cursor_#{idx}values instead of.attributes[:cursor_#{idx}], fixes #3149
- Stable Connections: use
.to_sqlto handle orderings that use complex Arel expressions (#3109)
- Pundit: add
pundit_policy_class_for(object, context)andpundit_role_for(object, context)for custom runtime lookups
- Subscriptions: don't send empty updates when subscriptions return
:no_update
- OperationStore: improve handling of archived operations in index views
(Oops, bad release!)
-
OperationStore: Store & display
last_used_atfor operation store clients and operations. To upgrade, add the column to your ActiveRecord table:add_column :graphql_client_operations, :last_used_at, :datetime
(It works out-of-the-box with the Redis backend.)
You can opt out of this feature by adding
use GraphQL::Pro::OperationStore, ... default_touch_last_used_at: falseto your schema setup. -
OperationStore: Add archive/unarchive workflow for operations. To upgrade, add the column to your table:
add_column :graphql_client_operations, :is_archived, :boolean, index: true
(It works out-of-the-box with the Redis backend.)
-
OperationStore: Fix indexing of enum values
- CanCan: Accept
can_can_attribute:configuration, which is passed as the third input to.can?(...)
- Add PubnubSubscriptions
- Update subscription implementations to support
broadcast: truewhen available
- More Ruby 2.7 warning fixes
- Return the proper
pageInfovalues when it's requested beforeedgesornodes(#2972)
- Fix some warnings on Ruby 2.7
- StableRelationConnection: properly return
hasNextPage: truewhenbeforeandmax_page_sizeare used.
GraphQL::Pro::OperationStore::Migrationcan be used to copy persisted operations from one backend to another (eg, ActiveRecord to Redis). See the source file,lib/graphql/pro/operation_store/migration.rbfor docs.
GraphQL::Pro::Subscriptionsis deprecated; useGraphQL::Pro::PusherSubscriptionsinstead which works the same, but better (see below). This new name avoids confusion with the later-addedAblySubscriptions.
GraphQL::Pro::PusherSubscriptionsreplacesGraphQL::Pro::Subscriptionsand adds orphaned record cleanup. (No more dangling records in Redis.)
- Use
nonce: truewhen working with cursors in new stable connections
- OperationStore supports a
redis:backend - OperationStore supports an arbitrary
backend_class:for persistence operations
- Use a loop when clearing Redis subscription state to avoid large stack traces #2701
- Handle empty subscription keys when publishing updates #2061
- Improve backwards compat with OperationStore (Improve adding
.tracer, use.graphql_namewhen indexing)
- Fix OperationStore on class-based schemas with query instrumenters that use the query string
GraphQL::Pro::Monitoringis deprecated; see Tracing for a replacement: https://graphql-ruby.org/queries/tracing.htmlGraphQL::Pro::Repositoryis deprecated; see OperationStore for a replacement: https://graphql-ruby.org/operation_store/overview.html
- New stable connection support based on GraphQL-Ruby 1.10's new pagination implementation. New classes provide better handling of
NULLvalues in order-by columns and they can be applied on a field-by-field basis(GraphQL::Pro::SqliteStableRelationConnection,GraphQL::Pro::MySQLStableRelationConnection,GraphQL::Pro::PostgresStableRelationConnection).
- Add the Access query analyzer to class-based schemas
- Forwards-compatibility for graphql 1.10.0
- Support 1.10.0.pre1's input object argument
loads:authorization
- Continue authorizing input object arguments
- Use millisecond-aware string format for datetimes in cursors
- Support multiple subscriptions in one document
- Support custom
#can_can_abilitymethods on query context for CanCanIntegration - Support custom
#pundit_usermethod on query context for PunditIntegration
- Fix off-by-one error when paginating backwards from the last item in a stable relation connection
- Include expected HMAC digest in OperationStore debug output
- Include content-length and content-type headers in OperationStore JSON responses
- Support stable connections ordered by Arel SQL literals
- Support stable connections on realized views (which don't have primary keys)
- Pundit integration: support
pundit_policy_classString names when scoping connections
- Add
GraphQL::Pro::Defer, implementing@deferfor streaming responses
- Pundit integration: correctly authorize fields when Query root is nil
- Pundit integration: use overridden
pundit_policy_classfor scoping and mutation authorization
- Pundit integration: Fields use the owner's configured
pundit_policy_classif there is one - Pundit integration: avoid conflicts with
#initializefor schema classes that don't need it
- Support inheritance with
pundit_policy_class(...)
- Support
pundit_policy_class(...)andpundit_policy_class:to manually specify a class or class name.
- Inject
contextinto policy lookup hooks instead of just the user
- Extract
pundit_policyandscope_by_pundit_policyhooks for user override
- Properly render subscription context in dashboard
- Don't pass arrays to Pundit scopes (fixes #2008)
- Prepare for future compat with graphql-ruby 1.9
- Include table name when adding a default order-by-id to ActiveRecord Relations
- Raise if a required cursor attribute is missing
- Improve
rake routesoutput for operation store endpoint - Support already-parsed queries in subscription RedisStorage
- Derp, remove the dummy app's
.logfiles from the gem bundle - Fix ordering bug when a SQL function call doesn't have an explicit order
- Fix Pusher reference in AblySubscriptions
- Add
GraphQL::Pro::AblySubscriptionsfor GraphQL subscriptions over Ably.io transport
- Support
NULLS LASTin stable cursors
- Improve operation store models to work when
config.active_record.primary_key_prefix_typeis set
- Support Rails 3.2 with OperationStore
- Use
.selectto filter items in CanCanIntegration
- Properly send an ability and the configured
can_can_actionto.accessible_by - Use a string (not integer) for
Content-Lengthheader in the dashboard
-
PunditIntegration: instead of raisingMutationAuthorizationFailedwhen an argument fails authorization, it will send aGraphQL::UnauthorizedErrorto yourSchema.unauthorized_objecthook. (This is what all other authorization failures do.) To retain the previous behavior, in your base mutation, add:def unauthorized_by_pundit(owner, value) # Raise a runtime error to halt query execution raise "#{value} failed #{owner}'s auth check" end
Otherwise, customize the handling of this behavior with
Schema.unauthorized_object.
- Auth: mutation arguments which have authorization constraints but don't load an object from the database will have mutation instance passed to the auth check, not the input value.
- Add
GraphQL::Pro::CanCanIntegrationwhich leverages GraphQL-Ruby's built-in auth
PunditIntegration: Don't try to authorize loaded objects when they'renil
- Update
PunditIntegrationfor arguments, unions, interfaces and mutations
- Add a new
PunditIntegrationwhich leverages the built-in authorization methods
- Authorization: fix scoping lists of abstract type when there's no
#scopemethod on the strategy
- Fix ordering of authorization field instrumenter (put it at the end, not the beginning of the list)
- Authorization: Add
view/access/authorizemethods toGraphQL::Schema::Mutation
- Authorization: when a
fallback:configuration is given, apply it to each field which doesn't have a configuration of its own or from its return type. Don't apply that configuration at schema level (it's applied to each otherwise uncovered field instead).
- Support Mongoid::Criteria in authorization scoping
- Fix authorization code for when
ActiveRecordis not defined
- Use a more permissive regexp (
/^\s*((?:[a-z._]+)\(.*\))\s*(asc|desc)?\s*$/im) to parse SQL functions
- Fix route helpers to support class-based schemas
- Support
1.8-preversions of GraphQL-Ruby
- Fix OperationStore when other query instrumenters need
.query_string
- Support
LEAST(...)in stable cursors
- Support
CASE ... ENDin stable cursors
- Support
FIELD(...)in stable cursors
- Improve detection of
OperationStorefor the dashboard - Serve
Content-TypeandContent-Lengthheaders with dashboard pages - Better
Dashboard#inspectfor Rails routes output - Use a string to apply order-by-primary-key for better Rails 3 support
- Support
composite_primary_keysgem
GraphQL::Pro::UIrenamed toGraphQL::Pro::Dashboard
- Routing method
.uiwas renamed to.dashboard
- Added
GraphQL::Pro::Subscriptions - Added subscriptions component to Dashboard
- Don't crash when scoping lists of abstract types with Pundit
- Use
authorize(:pundit, namespace: )to lookup policies in a namespace instead of the global namespace.
- Introspection data is allowed through
fallback:authorize:andaccess:filters. (It can be hidden with aview:filter.)
- Properly return
nilwhen a list of authorized objects returnsnil
- Add
authorization(..., operation_store:)option for authorizing operation store requests
- Support
ConnectionType.bidrectional_pagination?in stable RelationConnection
- Fix load issue when Rails is not present
-
Fix OperationStore views on PostgresQL
-
Fix stable cursors when joined tables have the same column names
Note: This is implemented by adding extra fields to the
SELECTclause with aliases likecursor_#{idx}, so you'll notice this in your SQL logs.
- Bump
graphqldependency to1.6
- Routing extensions moved to
using GraphQL::Pro::Routes
- Deprecate
using GraphQL::Pro, move extensions toGraphQL::Pro::Routes
- Add
GraphQL::Pro::OperationStorefor persisted queries with Rails
- Update
authorizationto use type-levelresolve_typehooks
- Update authorization instrumentation for
graphql >= 1.6.5
- Fix typo in RelationConnection source
- Correctly fall back to offset-based cursors with
before:argument
- Add
Schema#unauthorized_object(obj, ctx)hook for failed runtime checks
- Prevent usage of
parent_role:withview:oraccess:(since parent role requires a runtime check) - Fix versioned, encrypted cursors with 16-byte legacy cursors
OrderedRelationConnectionsupports ordering by joined fields
- Update auth plugin for new Relay instrumenters
Pro::Encodersupportsencoder(...)as documented
- Fix compatibility of
RelationConnectionandRangeAddhelper
- Add
:datadogmonitoring
ActiveRecord::Relations can be scoped by PunditScopes, CanCanaccessible_by, or custom strategy's#scope(gate, relation)methods- Default authorization configuration can be provided with
authorization(..., fallback: { ... }) - Authorization's
:current_userkey can be customized withauthorization(..., current_user: ...)
- Serve static, persisted queries with
GraphQL::Pro::Repository
- Fix compatibility of
RelationConnectionandRangeAddhelper
- Raise
GraphQL::Pro::RelationConnection::InvalidRelationErrorwhen a grouped, unordered relation is returned from a field. (This relation can't be stably paginated.)
- Formally support ActiveRecord
>= 4.1.0
- Support grouped relations in
GraphQL::Pro::RelationConnection
-
Authorize fields based on their parent object, for example:
AccountType = GraphQL::ObjectType.define do name "Account" # This field is visible to all users: field :name, types.String # This is only visible when the current user is an `:owner` # of this account field :account_balance, types.Int, authorize: { parent_role: :owner } end
- Fix monitoring when
Query#selected_operationis nil
- Add AppSignal monitoring platform
- Add type- and field-level opting in and opting out of monitoring
- Add
monitor_scalars: falseto skip monitoring on scalars
- Fix
OrderedRelationConnectionwhen neitherfirstnorlastare provided (usemax_page_sizeor don't limit)
OrderedRelationConnectionexposes more metadata methods:parent,field,arguments,max_page_size,first,after,last,before
- When an authorization check fails on a non-null field, propagate the null and add a response to the errors key (as if the field had returned null). It previously leaked the internal symbol
__graphql_pro_access_not_allowed__. - Apply a custom Pundit policy even when the value isn't
nil. (It previously fell back toPundit.policy, skipping apundit_policy_nameconfiguration.)
OrderedRelationConnectionexposes the underlying relation as#nodes(likeRelationConnectiondoes), supporting custom connection fields.
-
CanCan integration now supports a custom
Abilityclass with theability_class:option:authorize :cancan, ability_class: CustomAbility
GraphQL::Proreleased