Skip to content

Add optional permission hooks (can_create_blazer_queries?, can_access_blazer_query?)#520

Open
CesarOliveira wants to merge 3 commits intoankane:masterfrom
yardstik:permission-hooks
Open

Add optional permission hooks (can_create_blazer_queries?, can_access_blazer_query?)#520
CesarOliveira wants to merge 3 commits intoankane:masterfrom
yardstik:permission-hooks

Conversation

@CesarOliveira
Copy link
Copy Markdown

@CesarOliveira CesarOliveira commented Apr 21, 2026

Summary

Adds two optional, backwards-compatible permission hooks so host applications can gate Blazer actions on a per-user and per-query basis:

  • can_create_blazer_queries? — controls create/edit/update/destroy access across queries, dashboards, and checks.
  • can_access_blazer_query?(query) — controls per-query read access (show, edit, update, destroy, refresh, and the home page listing).

Both hooks delegate to the blazer_user object only when the method is defined, so existing Blazer installs (whose blazer_user doesn't implement these methods) behave exactly as they do today.

Motivation

In a multi-tenant / multi-team Rails app we wanted to let non-admin users reach Blazer while restricting:

  • who can author queries (writers vs. read-only viewers)
  • which queries each viewer can even see (per-team dashboards, sensitive data, etc.)

Today a host app has to monkey-patch Blazer controllers or duplicate Blazer behind an outer gate to do either. The hook surface here is small enough that it can live upstream without adding any new concept for existing users.

Behavior when the host app does nothing

# base_controller.rb
def can_create_blazer_queries?
  return true unless blazer_user.respond_to?(:can_create_blazer_queries?)
  blazer_user.can_create_blazer_queries?
end

def can_access_blazer_query?(query)
  return true unless blazer_user.respond_to?(:can_access_blazer_query?)
  blazer_user.can_access_blazer_query?(query)
end

If the host app's user class doesn't define either method, both hooks return true — identical to today's unrestricted behavior.

Where the hooks are wired in

Controller / View Gate
QueriesController show/edit/update/destroy/refresh authorize_blazer_query_access!can_access_blazer_query?(@query)
QueriesController new/create/edit/update/destroy authorize_blazer_create!can_create_blazer_queries?
DashboardsController new/create/edit/update/destroy authorize_blazer_create!
ChecksController new/create/edit/update/destroy authorize_blazer_create!
Home page query listing filtered via select { can_access_blazer_query?(q) }
Nav / queries#show / queries/_form / dashboards#show / dashboards/_form <% if can_create_blazer_queries? %> wraps New/Edit/Delete/Fork buttons

Host-app example

class User < ApplicationRecord
  def can_create_blazer_queries?
    admin?
  end

  def can_access_blazer_query?(query)
    return true if admin?

    # e.g. allow any query whose name starts with `[team]` to members of that team
    team_prefix = "[#{team.name}]"
    query.name.to_s.start_with?(team_prefix)
  end
end

Backwards compatibility

  • Both hooks are wrapped in respond_to? checks and default to true when the user class doesn't implement them.
  • No new gem config required.
  • No schema changes.
  • Existing test suite should continue to pass (no specs opted into the new hooks).

Happy to iterate on naming, placement, or behavior — feedback welcome.

CesarOliveira and others added 2 commits April 15, 2026 17:33
Add two backwards-compatible permission methods that are delegated
to the Blazer user object. These are only called if defined on the
user class, preserving full backwards compatibility:

- can_create_blazer_queries? — controls create/edit/delete access
- can_access_blazer_query?(query) — controls per-query read access

Controllers enforce these via before_actions. Views conditionally
hide New/Edit/Delete/Fork buttons. The home page query listing is
filtered through can_access_blazer_query?.

Host applications implement the actual logic by defining these
methods on their user model class.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The original permission-hooks commit wired authorize_blazer_create! to
[:new, :create, :edit, :update, :destroy] on dashboards and checks, but
only to [:new, :create] on queries. Consistent with the other
controllers now, so users without can_create_blazer_queries? can't edit
or delete queries either.
@CesarOliveira CesarOliveira marked this pull request as ready for review April 21, 2026 20:10
Adds can_access_blazer_dashboard?(dashboard) host-app hook plus the
matching authorize_blazer_dashboard_access! before_action, wired on the
dashboards controller (show/edit/update/destroy/refresh) and applied to
the dashboard listing on the queries home action. Backwards-compatible:
when the host app's blazer_user does not define the method, access is
allowed (mirrors the query-side hook).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant