Class: SuperAuth::Editor
- Inherits:
-
Object
- Object
- SuperAuth::Editor
- Defined in:
- lib/super_auth/editor.rb,
lib/super_auth/editor/cli.rb,
lib/super_auth/editor/seed.rb
Overview
A small Rack application that edits the authorization graph: five boxes of
records (groups, roles and resources drawn as trees), client-side
traversal, node and edge CRUD, and a Recompile button.
Rails-free; it needs only SuperAuth.db to be connected and the tables to
exist. Mount it as run SuperAuth::Editor (Rack) or
mount SuperAuth::Editor => "/super_auth/editor" (Rails), or run
super_auth-editor, which serves it on loopback.
It has no authentication of its own. Anyone who can reach it can rewrite
the graph, so the host must put its own authentication in front of the
mount. Two stdlib-only guards remain: writes must be application/json (a
cross-origin browser cannot send that without a CORS preflight, which is
never answered) and cross-site fetches are refused; hosts: additionally
rejects any other Host header, the DNS-rebinding defence the executable
turns on for loopback.
Edits change the graph, not runtime access: ByCurrentUser and the RLS policies read the compiled super_auth_authorizations table, so the UI shows its row count and offers POST /api/compile. A compile the models refuse (SuperAuth::Error, the wildcard guard) comes back as a 422 with the model's own message, like any other rejected write.
Defined Under Namespace
Constant Summary collapse
- TYPES =
{ "user" => :User, "group" => :Group, "role" => :Role, "permission" => :Permission, "resource" => :Resource, }.freeze
- COLUMNS =
{ "user" => :user_id, "group" => :group_id, "role" => :role_id, "permission" => :permission_id, "resource" => :resource_id, }.freeze
- NESTED =
%w[group role resource].freeze
- ALLOWED_PAIRS =
The pairs the path strategies read (see Edge.authorizations), unordered. The models also accept group->resource and role->resource rows, but no strategy reads them, so they would grant nothing.
[ %w[user group], %w[user role], %w[user permission], %w[user resource], %w[group role], %w[group permission], %w[role permission], %w[permission resource], ].map(&:sort).freeze
- EMPTY_EDGE =
{ user_id: nil, group_id: nil, role_id: nil, permission_id: nil, resource_id: nil }.freeze
- INDEX_HTML =
File.read(File.join(__dir__, "editor", "index.html")).freeze
- MAX_BODY =
64 * 1024
- ID =
/\A\d+\z/- NAME_MAX =
255
Class Method Summary collapse
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(hosts: nil) ⇒ Editor
constructor
hosts: host names (port ignored) this app answers to; nil disables the check.
Constructor Details
#initialize(hosts: nil) ⇒ Editor
hosts: host names (port ignored) this app answers to; nil disables the check.
54 55 56 |
# File 'lib/super_auth/editor.rb', line 54 def initialize(hosts: nil) @hosts = hosts && hosts.map { |h| h.to_s.downcase } end |
Class Method Details
.call(env) ⇒ Object
49 50 51 |
# File 'lib/super_auth/editor.rb', line 49 def self.call(env) (@default ||= new).call(env) end |
Instance Method Details
#call(env) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/super_auth/editor.rb', line 58 def call(env) return forbidden("host not allowed") if @hosts && !@hosts.include?(host_of(env)) begin SuperAuth.load unless defined?(SuperAuth::User) rescue Sequel::DatabaseError return json(503, error: "super_auth tables not found; run the migrations (super_auth-editor --migrate, or your application's)") end method = env["REQUEST_METHOD"] path = env["PATH_INFO"].to_s path = "/" if path.empty? if %w[POST DELETE].include?(method) && env["HTTP_SEC_FETCH_SITE"] == "cross-site" return forbidden("cross-site requests are not accepted") end route(method, path, env) rescue SuperAuth::Error => e json(422, error: e.) rescue Sequel::Error json(422, error: "the database rejected the change") end |