current_scope 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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +577 -0
- data/Rakefile +6 -0
- data/app/assets/javascripts/current_scope/application.js +225 -0
- data/app/assets/stylesheets/current_scope/application.css +707 -0
- data/app/controllers/current_scope/application_controller.rb +54 -0
- data/app/controllers/current_scope/events_controller.rb +14 -0
- data/app/controllers/current_scope/role_assignments_controller.rb +104 -0
- data/app/controllers/current_scope/roles_controller.rb +135 -0
- data/app/controllers/current_scope/scoped_role_assignments_controller.rb +159 -0
- data/app/controllers/current_scope/subjects_controller.rb +57 -0
- data/app/helpers/current_scope/application_helper.rb +72 -0
- data/app/models/current_scope/application_record.rb +5 -0
- data/app/models/current_scope/current.rb +50 -0
- data/app/models/current_scope/event.rb +117 -0
- data/app/models/current_scope/role.rb +55 -0
- data/app/models/current_scope/role_assignment.rb +21 -0
- data/app/models/current_scope/role_permission.rb +9 -0
- data/app/models/current_scope/scoped_role_assignment.rb +14 -0
- data/app/views/current_scope/events/index.html.erb +41 -0
- data/app/views/current_scope/roles/edit.html.erb +86 -0
- data/app/views/current_scope/roles/index.html.erb +41 -0
- data/app/views/current_scope/roles/members.html.erb +96 -0
- data/app/views/current_scope/roles/new.html.erb +19 -0
- data/app/views/current_scope/scoped_role_assignments/new.html.erb +135 -0
- data/app/views/current_scope/subjects/index.html.erb +100 -0
- data/app/views/layouts/current_scope/application.html.erb +53 -0
- data/config/routes.rb +14 -0
- data/db/migrate/20260710000001_create_current_scope_tables.rb +31 -0
- data/db/migrate/20260710000002_create_current_scope_events.rb +32 -0
- data/db/migrate/20260714000001_add_description_to_current_scope_roles.rb +5 -0
- data/lib/current_scope/configuration.rb +181 -0
- data/lib/current_scope/context.rb +36 -0
- data/lib/current_scope/engine.rb +14 -0
- data/lib/current_scope/gating_tripwire.rb +53 -0
- data/lib/current_scope/guard.rb +97 -0
- data/lib/current_scope/mutation_guard.rb +55 -0
- data/lib/current_scope/permission_catalog.rb +33 -0
- data/lib/current_scope/permission_grid.rb +90 -0
- data/lib/current_scope/permissions.rb +57 -0
- data/lib/current_scope/resolver.rb +171 -0
- data/lib/current_scope/scopeable.rb +38 -0
- data/lib/current_scope/test_helpers.rb +53 -0
- data/lib/current_scope/version.rb +3 -0
- data/lib/current_scope.rb +168 -0
- data/lib/generators/current_scope/install/install_generator.rb +33 -0
- data/lib/generators/current_scope/install/templates/initializer.rb +77 -0
- data/lib/tasks/current_scope_tasks.rake +15 -0
- metadata +113 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module CurrentScope
|
|
2
|
+
module Generators
|
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
|
4
|
+
source_root File.expand_path("templates", __dir__)
|
|
5
|
+
|
|
6
|
+
def copy_initializer
|
|
7
|
+
template "initializer.rb", "config/initializers/current_scope.rb"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def mount_engine
|
|
11
|
+
route 'mount CurrentScope::Engine => "/current_scope"'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def show_next_steps
|
|
15
|
+
say <<~NEXT
|
|
16
|
+
|
|
17
|
+
CurrentScope installed. Next steps:
|
|
18
|
+
|
|
19
|
+
1. bin/rails current_scope:install:migrations && bin/rails db:migrate
|
|
20
|
+
2. Include the concerns in ApplicationController (Context first):
|
|
21
|
+
include CurrentScope::Context
|
|
22
|
+
include CurrentScope::Guard
|
|
23
|
+
3. Seed the baseline roles and give yourself full access, e.g. in db/seeds.rb:
|
|
24
|
+
CurrentScope.seed_defaults!
|
|
25
|
+
CurrentScope::RoleAssignment.create!(
|
|
26
|
+
subject: User.first, role: CurrentScope::Role.find_by!(name: "Owner"))
|
|
27
|
+
4. Manage roles at /current_scope (full-access subjects only).
|
|
28
|
+
|
|
29
|
+
NEXT
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
CurrentScope.configure do |config|
|
|
2
|
+
# Controller method that returns the authenticated subject.
|
|
3
|
+
# config.user_method = :current_user
|
|
4
|
+
|
|
5
|
+
# Class whose instances hold roles, used by the management UI.
|
|
6
|
+
# config.subject_class = "User"
|
|
7
|
+
|
|
8
|
+
# How a subject is identified in the management UI (an id is meaningless with
|
|
9
|
+
# UUID keys). A Symbol names a method; a Proc takes the subject. Defaults to a
|
|
10
|
+
# best-effort label (current_scope_label, else name/email/title, else id).
|
|
11
|
+
# config.subject_label = :email
|
|
12
|
+
# config.subject_label = ->(u) { "#{u.first_name} #{u.last_name}" }
|
|
13
|
+
|
|
14
|
+
# Fold the role-editor grid's action columns. Default = CRUD (new/edit hide
|
|
15
|
+
# into create/update; index+show read as one). Set to nil to show every raw
|
|
16
|
+
# action as its own column.
|
|
17
|
+
# config.permission_grid_groups = { "read" => %w[index show], "create" => %w[new create],
|
|
18
|
+
# "update" => %w[edit update], "destroy" => %w[destroy] }
|
|
19
|
+
|
|
20
|
+
# --- Impersonation (act-as) ---------------------------------------------
|
|
21
|
+
# These three knobs layer, in this order:
|
|
22
|
+
#
|
|
23
|
+
# 1. actor_method — turns impersonation ON.
|
|
24
|
+
# 2. allow_mutations_while_impersonating — the read-only gate runs FIRST.
|
|
25
|
+
# 3. sod_identity — only observable once a mutation
|
|
26
|
+
# is allowed through (or on a
|
|
27
|
+
# GET-listed sod_action).
|
|
28
|
+
#
|
|
29
|
+
# Controller method returning the REAL actor while impersonating. Leave unset
|
|
30
|
+
# when no one impersonates — actor then equals the subject, so attribution
|
|
31
|
+
# reads current_scope_actor with no nil branch, and sod_identity below has no
|
|
32
|
+
# effect. See the "Impersonation (act-as)" section of the README.
|
|
33
|
+
# config.actor_method = :true_user
|
|
34
|
+
|
|
35
|
+
# false (default): an impersonated session is read-only — every non-GET/HEAD
|
|
36
|
+
# request is denied, INCLUDING the engine's management UI. Your
|
|
37
|
+
# stop-impersonation, sign-out, and sign-in endpoints must opt out with
|
|
38
|
+
# skip_before_action :current_scope_mutation_guard!, or impersonation (and
|
|
39
|
+
# sign-in) can never clear it.
|
|
40
|
+
# config.allow_mutations_while_impersonating = false
|
|
41
|
+
|
|
42
|
+
# Which identities the separation-of-duties veto weighs. :either (default)
|
|
43
|
+
# also vetoes a record the REAL actor initiated while impersonating, so
|
|
44
|
+
# impersonation can never approve your own record. :subject weighs only the
|
|
45
|
+
# effective subject. Identical when not impersonating.
|
|
46
|
+
# config.sod_identity = :either
|
|
47
|
+
# ------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
# Separation of duties is OPT-IN — empty by default. List the actions a
|
|
50
|
+
# record's initiator can never perform on their own record (four-eyes).
|
|
51
|
+
# Deliberately NOT editable in the UI. Records reached by these actions must
|
|
52
|
+
# define current_scope_initiator (return nil to exempt a record type) — the
|
|
53
|
+
# resolver raises if the hook is missing. Leave commented for RBAC-only apps.
|
|
54
|
+
# config.sod_actions = %w[approve]
|
|
55
|
+
|
|
56
|
+
# Audit ledger — tri-state: false | true (default) | :strict.
|
|
57
|
+
# false — no audit rows recorded.
|
|
58
|
+
# true — record every authorization change; if the events table hasn't
|
|
59
|
+
# been migrated yet, degrade gracefully (skip + warn once).
|
|
60
|
+
# :strict — a missing events table RAISES (rolling the mutation back), so an
|
|
61
|
+
# audit-mandatory app never commits an unaudited change.
|
|
62
|
+
# config.audit = true
|
|
63
|
+
|
|
64
|
+
# Dev/test aid: log a nudge when an SoD action is ALLOWED but was gated with a
|
|
65
|
+
# nil record — i.e. the SoD veto was silently skipped because
|
|
66
|
+
# current_scope_record returned nil on a member action. Off by default; never
|
|
67
|
+
# changes behavior.
|
|
68
|
+
# config.warn_on_nil_sod_record = false
|
|
69
|
+
|
|
70
|
+
# Controller paths (regexps) excluded from the permission grid. Excluded
|
|
71
|
+
# controllers can't be granted, so they must also skip the gate with
|
|
72
|
+
# skip_before_action :current_scope_check! — Guard raises otherwise.
|
|
73
|
+
# config.excluded_controllers += [%r{\Awebhooks/}]
|
|
74
|
+
|
|
75
|
+
# Controller the management UI inherits from (for host auth + before_actions).
|
|
76
|
+
# config.parent_controller = "::ApplicationController"
|
|
77
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
namespace :current_scope do
|
|
2
|
+
desc "Grant the full-access Owner role to a subject (bootstrap the first admin). " \
|
|
3
|
+
"Usage: bin/rails current_scope:grant SUBJECT_ID=1"
|
|
4
|
+
task grant: :environment do
|
|
5
|
+
id = ENV["SUBJECT_ID"]
|
|
6
|
+
abort "SUBJECT_ID is required, e.g. bin/rails current_scope:grant SUBJECT_ID=1" if id.blank?
|
|
7
|
+
|
|
8
|
+
klass = CurrentScope.config.subject_class.constantize
|
|
9
|
+
subject = klass.find_by(id: id)
|
|
10
|
+
abort "No #{klass} with id=#{id}" if subject.nil?
|
|
11
|
+
|
|
12
|
+
CurrentScope.grant!(subject)
|
|
13
|
+
puts "Granted the full-access Owner role to #{klass}##{subject.id}."
|
|
14
|
+
end
|
|
15
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: current_scope
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- David Teren
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rails
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '8.1'
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '9'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '8.1'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '9'
|
|
32
|
+
description: 'A mountable Rails engine for authorization: permissions auto-derived
|
|
33
|
+
from controller actions, roles as editable data, per-record scoped roles, a separation-of-duties
|
|
34
|
+
veto, and an ambient authorization context that makes allowed_to? work identically
|
|
35
|
+
in controllers, views, and components.'
|
|
36
|
+
email:
|
|
37
|
+
- dteren@gmail.com
|
|
38
|
+
executables: []
|
|
39
|
+
extensions: []
|
|
40
|
+
extra_rdoc_files: []
|
|
41
|
+
files:
|
|
42
|
+
- MIT-LICENSE
|
|
43
|
+
- README.md
|
|
44
|
+
- Rakefile
|
|
45
|
+
- app/assets/javascripts/current_scope/application.js
|
|
46
|
+
- app/assets/stylesheets/current_scope/application.css
|
|
47
|
+
- app/controllers/current_scope/application_controller.rb
|
|
48
|
+
- app/controllers/current_scope/events_controller.rb
|
|
49
|
+
- app/controllers/current_scope/role_assignments_controller.rb
|
|
50
|
+
- app/controllers/current_scope/roles_controller.rb
|
|
51
|
+
- app/controllers/current_scope/scoped_role_assignments_controller.rb
|
|
52
|
+
- app/controllers/current_scope/subjects_controller.rb
|
|
53
|
+
- app/helpers/current_scope/application_helper.rb
|
|
54
|
+
- app/models/current_scope/application_record.rb
|
|
55
|
+
- app/models/current_scope/current.rb
|
|
56
|
+
- app/models/current_scope/event.rb
|
|
57
|
+
- app/models/current_scope/role.rb
|
|
58
|
+
- app/models/current_scope/role_assignment.rb
|
|
59
|
+
- app/models/current_scope/role_permission.rb
|
|
60
|
+
- app/models/current_scope/scoped_role_assignment.rb
|
|
61
|
+
- app/views/current_scope/events/index.html.erb
|
|
62
|
+
- app/views/current_scope/roles/edit.html.erb
|
|
63
|
+
- app/views/current_scope/roles/index.html.erb
|
|
64
|
+
- app/views/current_scope/roles/members.html.erb
|
|
65
|
+
- app/views/current_scope/roles/new.html.erb
|
|
66
|
+
- app/views/current_scope/scoped_role_assignments/new.html.erb
|
|
67
|
+
- app/views/current_scope/subjects/index.html.erb
|
|
68
|
+
- app/views/layouts/current_scope/application.html.erb
|
|
69
|
+
- config/routes.rb
|
|
70
|
+
- db/migrate/20260710000001_create_current_scope_tables.rb
|
|
71
|
+
- db/migrate/20260710000002_create_current_scope_events.rb
|
|
72
|
+
- db/migrate/20260714000001_add_description_to_current_scope_roles.rb
|
|
73
|
+
- lib/current_scope.rb
|
|
74
|
+
- lib/current_scope/configuration.rb
|
|
75
|
+
- lib/current_scope/context.rb
|
|
76
|
+
- lib/current_scope/engine.rb
|
|
77
|
+
- lib/current_scope/gating_tripwire.rb
|
|
78
|
+
- lib/current_scope/guard.rb
|
|
79
|
+
- lib/current_scope/mutation_guard.rb
|
|
80
|
+
- lib/current_scope/permission_catalog.rb
|
|
81
|
+
- lib/current_scope/permission_grid.rb
|
|
82
|
+
- lib/current_scope/permissions.rb
|
|
83
|
+
- lib/current_scope/resolver.rb
|
|
84
|
+
- lib/current_scope/scopeable.rb
|
|
85
|
+
- lib/current_scope/test_helpers.rb
|
|
86
|
+
- lib/current_scope/version.rb
|
|
87
|
+
- lib/generators/current_scope/install/install_generator.rb
|
|
88
|
+
- lib/generators/current_scope/install/templates/initializer.rb
|
|
89
|
+
- lib/tasks/current_scope_tasks.rake
|
|
90
|
+
homepage: https://github.com/davidteren/current_scope
|
|
91
|
+
licenses:
|
|
92
|
+
- MIT
|
|
93
|
+
metadata:
|
|
94
|
+
changelog_uri: https://github.com/davidteren/current_scope/blob/main/CHANGELOG.md
|
|
95
|
+
rubygems_mfa_required: 'true'
|
|
96
|
+
rdoc_options: []
|
|
97
|
+
require_paths:
|
|
98
|
+
- lib
|
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '3.2'
|
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
|
+
requirements:
|
|
106
|
+
- - ">="
|
|
107
|
+
- !ruby/object:Gem::Version
|
|
108
|
+
version: '0'
|
|
109
|
+
requirements: []
|
|
110
|
+
rubygems_version: 3.6.9
|
|
111
|
+
specification_version: 4
|
|
112
|
+
summary: Data-driven authorization for Rails with an ambient current-user context.
|
|
113
|
+
test_files: []
|