placet-rails 0.1.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/LICENSE +21 -0
- data/README.md +49 -0
- data/lib/placet/rails/active_record_scope.rb +34 -0
- data/lib/placet/rails/controller.rb +149 -0
- data/lib/placet/rails/railtie.rb +31 -0
- data/lib/placet/rails/version.rb +7 -0
- data/lib/placet/rails.rb +7 -0
- data/lib/placet-rails.rb +3 -0
- data/lib/tasks/placet.rake +46 -0
- metadata +113 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: db4bfcb4a459bf5fa9fa800a098e9ac53b7270e18c4d6e169188b6aec61f5858
|
|
4
|
+
data.tar.gz: 5bd4e349f816f0dab05a594330e13b367b0573ba0767f51c085064fdfa6f1cd7
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d1bef0f2695c4ff710efc1769b95e1376f82cb46addb4821181caf2a7aef4bf12f939ecc2ebb87bdf2eb3252de9622b915e74eda9ed5a1b15f49328d39fa913a
|
|
7
|
+
data.tar.gz: 1e1fd5cabd3b03328dc796df594e2a8ca1fdd68f8c76b64b3137dd56012335f988ea154d9e0b8a236f3a7d635b92eb4b85727039b2fc4309398005d5075c0761
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yugo TERADA
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# placet-rails
|
|
2
|
+
|
|
3
|
+
> placet の Rails アダプタ — 宣言的な per-action 認可と ActiveRecord への scope 合成
|
|
4
|
+
|
|
5
|
+
[placet](../../README.md) を Rails に統合するアダプタ gem。設計の全体像は [docs/rails-usage.md](../../docs/rails-usage.md) を参照。
|
|
6
|
+
|
|
7
|
+
## インストール
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
# Gemfile
|
|
11
|
+
gem "placet-rails" # placet 本体も依存として入る
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## 提供するもの
|
|
15
|
+
|
|
16
|
+
- **コントローラ統合(PEP ヘルパー)** — `placet_permit`(check / scope の 2 モード、複数 action は AND)、`placet_resource`(RESTful 規約の展開)、`placet_public`(明示オプトアウト)、`placet_verify!`(enforcement 漏れの検知)、`placet_scope` / `placet_permit?` ヘルパー
|
|
17
|
+
- **ActiveRecord への scope 写像** — コアの ScopePlan(empty / all / union ± exclude)を主キーのサブクエリとして `ActiveRecord::Relation` に合成する。返るのは素の Relation なので、ページネーション・ORDER・`count` がそのまま動く
|
|
18
|
+
- **Railtie** — `config/placet/**/*.rb` の定義を起動時にロード(不備は起動エラー)。`rails placet:export` / `rails placet:endpoints` タスク
|
|
19
|
+
|
|
20
|
+
## 使い方の骨子
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
class ApplicationController < ActionController::Base
|
|
24
|
+
include Placet::Rails::Controller
|
|
25
|
+
placet_verify!
|
|
26
|
+
|
|
27
|
+
rescue_from Placet::Denied do |error|
|
|
28
|
+
Rails.logger.info(error.decision.to_h) # 根拠は監査ログへ
|
|
29
|
+
head :forbidden # ユーザーには理由を出さない
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class PostsController < ApplicationController
|
|
34
|
+
before_action :set_post, only: %i[update destroy]
|
|
35
|
+
placet_resource Post
|
|
36
|
+
placet_permit "post:publish", only: :publish, resource: -> { @post }
|
|
37
|
+
|
|
38
|
+
def index = render(json: placet_scope.order(created_at: :desc).page(params[:page]))
|
|
39
|
+
def show = render(json: placet_scope.find(params[:id])) # 見えなければ 404
|
|
40
|
+
end
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## テストの実行
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
cd packages/rails
|
|
47
|
+
bundle install
|
|
48
|
+
for f in test/*_test.rb; do bundle exec ruby -Ilib -Itest "$f"; done
|
|
49
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Placet
|
|
4
|
+
module Rails
|
|
5
|
+
# ScopePlan → ActiveRecord::Relation の写像(concept.md 8.4 の集合演算を SQL に落とす)。
|
|
6
|
+
# relation の scope 同士の構造差(joins の有無など)に依存しないよう、
|
|
7
|
+
# 和集合・差集合は主キーのサブクエリとして合成する
|
|
8
|
+
module ActiveRecordScope
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
def compose(plan, relations, user, model)
|
|
12
|
+
return model.none if plan.kind == "empty"
|
|
13
|
+
|
|
14
|
+
pk = model.primary_key
|
|
15
|
+
base =
|
|
16
|
+
if plan.kind == "all"
|
|
17
|
+
model.all
|
|
18
|
+
else
|
|
19
|
+
Placet.relation_scopes(relations, plan.include_relations, user)
|
|
20
|
+
.map { |scope| model.where(pk => scope.select(pk)) }
|
|
21
|
+
.reduce { |a, b| a.or(b) }
|
|
22
|
+
end
|
|
23
|
+
Placet.relation_scopes(relations, plan.exclude_relations, user)
|
|
24
|
+
.reduce(base) { |rel, scope| rel.where.not(pk => scope.select(pk)) }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# ActiveRecord モデルに対する ScopePlan の実体化として登録する
|
|
31
|
+
Placet.register_scope_materializer(
|
|
32
|
+
->(model) { defined?(ActiveRecord::Base) && model.is_a?(Class) && model <= ActiveRecord::Base },
|
|
33
|
+
Placet::Rails::ActiveRecordScope.method(:compose)
|
|
34
|
+
)
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/concern"
|
|
4
|
+
|
|
5
|
+
module Placet
|
|
6
|
+
module Rails
|
|
7
|
+
# placet_verify! が enforcement 漏れを検出したときに送出される
|
|
8
|
+
class VerificationError < Placet::Error; end
|
|
9
|
+
|
|
10
|
+
# コントローラ統合(PEP ヘルパー。docs/rails-usage.md Section 4)
|
|
11
|
+
#
|
|
12
|
+
# class ApplicationController < ActionController::Base
|
|
13
|
+
# include Placet::Rails::Controller
|
|
14
|
+
# placet_verify!
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
# class PostsController < ApplicationController
|
|
18
|
+
# before_action :set_post, only: %i[update destroy]
|
|
19
|
+
# placet_resource Post
|
|
20
|
+
# placet_permit "post:publish", only: :publish, resource: -> { @post }
|
|
21
|
+
# end
|
|
22
|
+
module Controller
|
|
23
|
+
extend ActiveSupport::Concern
|
|
24
|
+
|
|
25
|
+
included do
|
|
26
|
+
class_attribute :placet_declarations, default: {}, instance_writer: false
|
|
27
|
+
class_attribute :placet_public_actions, default: [], instance_writer: false
|
|
28
|
+
class_attribute :placet_verify_enabled, default: false, instance_writer: false
|
|
29
|
+
class_attribute :placet_enforcer_installed, default: false, instance_writer: false
|
|
30
|
+
helper_method :placet_permit?, :placet_user if respond_to?(:helper_method)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class_methods do
|
|
34
|
+
# action ごとの権限宣言。
|
|
35
|
+
# via: :check — before_action として authorize! を実行(403)
|
|
36
|
+
# via: :scope — placet_scope で合成済みコレクションを取得(絞り込み / 404)
|
|
37
|
+
# 複数 action は AND。via: :scope は単一 action のみ(docs/rails-usage.md 4.2)
|
|
38
|
+
def placet_permit(actions, only:, via: :check, resource: nil, model: nil)
|
|
39
|
+
actions = Array(actions).map(&:to_s)
|
|
40
|
+
if via == :scope && actions.size > 1
|
|
41
|
+
raise Placet::DefinitionError, "via: :scope の宣言は単一 action のみ: #{actions.inspect}"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# typo は「静かな全拒否 / 空 scope」になるため宣言時に検査する(検証規則はコアに一元化)
|
|
45
|
+
actions.each { |action| Placet.validate_action!(action, error_class: Placet::DefinitionError) }
|
|
46
|
+
|
|
47
|
+
declaration = { actions: actions, via: via, resource: resource, model: model }
|
|
48
|
+
if via == :scope && model.nil?
|
|
49
|
+
# 規約推論(resource セグメント → モデル名)は宣言時に解決しておく。
|
|
50
|
+
# リロードと相性を保つため、クラス参照ではなく名前文字列を保持する
|
|
51
|
+
declaration[:model_name] = actions.first.split(":", 2).first.camelize
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
merged = Array(only).map(&:to_s).to_h { |name| [name, (placet_declarations[name] || []) + [declaration]] }
|
|
55
|
+
self.placet_declarations = placet_declarations.merge(merged)
|
|
56
|
+
|
|
57
|
+
install_placet_enforcer if via == :check
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# RESTful CRUD の規約展開(docs/rails-usage.md 4.1)。
|
|
61
|
+
# index/show → <resource>:view (scope)、create/update/destroy → check。
|
|
62
|
+
# リソースのロードは肩代わりしない: update/destroy は @<resource> を参照する
|
|
63
|
+
def placet_resource(model)
|
|
64
|
+
name = model.name.underscore
|
|
65
|
+
ref = -> { instance_variable_get(:"@#{name}") }
|
|
66
|
+
placet_permit "#{name}:view", only: %i[index show], via: :scope, model: model
|
|
67
|
+
placet_permit "#{name}:create", only: :create
|
|
68
|
+
placet_permit "#{name}:update", only: :update, resource: ref
|
|
69
|
+
placet_permit "#{name}:delete", only: :destroy, resource: ref
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# 認可不要のエンドポイントを明示的にオプトアウトする(verify の対象から外す唯一の方法)
|
|
73
|
+
def placet_public(only:)
|
|
74
|
+
self.placet_public_actions = placet_public_actions + Array(only).map(&:to_s)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# enforcement(authorize! / scoped)が一度も行われずにアクションが終わったら raise。
|
|
78
|
+
# development / test で必ず有効化することを推奨(docs/rails-usage.md 4.4)
|
|
79
|
+
def placet_verify!
|
|
80
|
+
return if placet_verify_enabled
|
|
81
|
+
|
|
82
|
+
self.placet_verify_enabled = true
|
|
83
|
+
prepend_before_action { @_placet_enforcements_before = Placet.enforcements }
|
|
84
|
+
after_action :placet_verify_enforcement!
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
# check モードの enforcement は、宣言ハッシュを唯一の真実として 1 本の
|
|
90
|
+
# before_action で行う(endpoints タスク・verify と同じデータを見る)。
|
|
91
|
+
# 最初の check 宣言の位置で登録されるため、リソースをロードする
|
|
92
|
+
# before_action はそれより前に宣言しておくこと
|
|
93
|
+
def install_placet_enforcer
|
|
94
|
+
return if placet_enforcer_installed
|
|
95
|
+
|
|
96
|
+
self.placet_enforcer_installed = true
|
|
97
|
+
before_action :placet_enforce!
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# アプリ側で上書き可能。既定は current_user
|
|
102
|
+
def placet_user = current_user
|
|
103
|
+
|
|
104
|
+
# via: :scope の宣言から合成済みコレクション(AR なら Relation)を返す
|
|
105
|
+
def placet_scope(model = nil)
|
|
106
|
+
declaration = placet_scope_declaration!
|
|
107
|
+
target = model || declaration[:model] || declaration[:model_name].constantize
|
|
108
|
+
Placet.scoped(placet_user, declaration[:actions].first, model: target)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# 表示制御用。enforcement にはカウントされない
|
|
112
|
+
def placet_permit?(actions, resource = nil) = Placet.permit?(placet_user, actions, resource)
|
|
113
|
+
|
|
114
|
+
# 二段構えの再チェック(docs/rails-usage.md Section 6)。scope で絞った結果
|
|
115
|
+
# (通常は 1 ページ分)へ個体判定を再適用し、check / scope の乖離があっても
|
|
116
|
+
# 見えてはいけないレコードを返さない。action 省略時は scope 宣言から引き継ぐ
|
|
117
|
+
def placet_recheck(records, action: nil)
|
|
118
|
+
action ||= placet_scope_declaration![:actions].first
|
|
119
|
+
Placet.recheck(placet_user, action, records)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
private
|
|
123
|
+
|
|
124
|
+
def placet_scope_declaration!
|
|
125
|
+
(placet_declarations[action_name] || []).find { |d| d[:via] == :scope } ||
|
|
126
|
+
raise(Placet::Error, "#{self.class.name}##{action_name} に via: :scope の宣言がない")
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def placet_enforce!
|
|
130
|
+
(placet_declarations[action_name] || []).each do |declaration|
|
|
131
|
+
next unless declaration[:via] == :check
|
|
132
|
+
|
|
133
|
+
target = declaration[:resource] && instance_exec(&declaration[:resource])
|
|
134
|
+
Placet.authorize!(placet_user, declaration[:actions], target)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def placet_verify_enforcement!
|
|
139
|
+
return if placet_public_actions.include?(action_name)
|
|
140
|
+
return if Placet.enforcements > (@_placet_enforcements_before || 0)
|
|
141
|
+
|
|
142
|
+
raise VerificationError,
|
|
143
|
+
"#{self.class.name}##{action_name} で認可が行われていない。" \
|
|
144
|
+
"placet_permit / placet_resource で宣言するか、placet_scope / Placet.authorize! を呼ぶか、" \
|
|
145
|
+
"認可不要なら placet_public で明示すること"
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Placet
|
|
4
|
+
module Rails
|
|
5
|
+
class Railtie < ::Rails::Railtie
|
|
6
|
+
config.placet = ActiveSupport::OrderedOptions.new
|
|
7
|
+
|
|
8
|
+
# config/placet/**/*.rb(1 ファイル 1 ポリシー + actions.rb 等)を起動時にロードする。
|
|
9
|
+
# 定義の不備は DefinitionError となり、起動が失敗する(fail fast)
|
|
10
|
+
initializer "placet.load_definitions", after: :load_config_initializers do |app|
|
|
11
|
+
paths = app.config.placet.definition_paths ||
|
|
12
|
+
[app.root.join("config", "placet", "**", "*.rb").to_s]
|
|
13
|
+
paths.flat_map { |pattern| Dir[pattern.to_s].sort }.each { |file| load file }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# 再チェック(Placet.recheck / placet_recheck)で乖離を検出したときの既定通知
|
|
17
|
+
initializer "placet.recheck_divergence_logging" do
|
|
18
|
+
Placet.on_recheck_divergence ||= lambda do |_user, action, record|
|
|
19
|
+
::Rails.logger.warn(
|
|
20
|
+
"placet: scope と check の乖離を検出 action=#{action} " \
|
|
21
|
+
"record=#{record.class}##{record.respond_to?(:id) ? record.id : record.inspect}"
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
rake_tasks do
|
|
27
|
+
load File.expand_path("../../tasks/placet.rake", __dir__)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/placet/rails.rb
ADDED
data/lib/placet-rails.rb
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :placet do
|
|
4
|
+
desc "コンパイル済みの正規形(canonical form)を JSON で出力する"
|
|
5
|
+
task export: :environment do
|
|
6
|
+
require "json"
|
|
7
|
+
puts JSON.pretty_generate(Placet.export)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
desc "principal の実効権限、または principal 集合 × action の決定根拠を表示する"
|
|
11
|
+
task :explain, %i[subject action] => :environment do |_t, args|
|
|
12
|
+
subject = args[:subject].to_s.strip
|
|
13
|
+
action = args[:action].to_s.strip
|
|
14
|
+
if subject.empty?
|
|
15
|
+
abort 'usage: rails "placet:explain[tenant:acme]" / ' \
|
|
16
|
+
'rails "placet:explain[role:editor flag:suspended, post:update]"'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
principals = subject.split(/\s+/)
|
|
20
|
+
if action.empty?
|
|
21
|
+
abort "principal の説明は 1 つずつ指定してください" if principals.size > 1
|
|
22
|
+
puts Placet::Explain.principal_report(principals.first)
|
|
23
|
+
else
|
|
24
|
+
puts Placet::Explain.decision_report(principals, action)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
desc "コントローラの宣言から エンドポイント → 必要権限 の一覧を出力する"
|
|
29
|
+
task endpoints: :environment do
|
|
30
|
+
Rails.application.eager_load!
|
|
31
|
+
controllers = ActionController::Base.descendants
|
|
32
|
+
.select { |c| c.respond_to?(:placet_declarations) }
|
|
33
|
+
.sort_by(&:name)
|
|
34
|
+
controllers.each do |controller|
|
|
35
|
+
controller.placet_declarations.sort.each do |action_name, declarations|
|
|
36
|
+
declarations.each do |decl|
|
|
37
|
+
mode = decl[:via] == :scope ? "(scoped)" : "(403)"
|
|
38
|
+
puts format("%-40s %-30s %s", "#{controller.name}##{action_name}", decl[:actions].join(" AND "), mode)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
controller.placet_public_actions.each do |action_name|
|
|
42
|
+
puts format("%-40s %-30s %s", "#{controller.name}##{action_name}", "-", "(public)")
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: placet-rails
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Yugo TERADA
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-07-11 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: placet
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 0.1.0
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 0.1.0
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: actionpack
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '7.1'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '7.1'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: activesupport
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '7.1'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '7.1'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: railties
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '7.1'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '7.1'
|
|
69
|
+
description: 'placet-rails integrates the placet authorization library with Rails:
|
|
70
|
+
per-action permission declarations (placet_permit / placet_resource), an enforcement
|
|
71
|
+
verification hook, and mapping of placet scope plans onto ActiveRecord relations
|
|
72
|
+
for list filtering.'
|
|
73
|
+
email:
|
|
74
|
+
executables: []
|
|
75
|
+
extensions: []
|
|
76
|
+
extra_rdoc_files: []
|
|
77
|
+
files:
|
|
78
|
+
- LICENSE
|
|
79
|
+
- README.md
|
|
80
|
+
- lib/placet-rails.rb
|
|
81
|
+
- lib/placet/rails.rb
|
|
82
|
+
- lib/placet/rails/active_record_scope.rb
|
|
83
|
+
- lib/placet/rails/controller.rb
|
|
84
|
+
- lib/placet/rails/railtie.rb
|
|
85
|
+
- lib/placet/rails/version.rb
|
|
86
|
+
- lib/tasks/placet.rake
|
|
87
|
+
homepage: https://github.com/aspick/placet
|
|
88
|
+
licenses:
|
|
89
|
+
- MIT
|
|
90
|
+
metadata:
|
|
91
|
+
homepage_uri: https://github.com/aspick/placet
|
|
92
|
+
source_code_uri: https://github.com/aspick/placet
|
|
93
|
+
post_install_message:
|
|
94
|
+
rdoc_options: []
|
|
95
|
+
require_paths:
|
|
96
|
+
- lib
|
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
98
|
+
requirements:
|
|
99
|
+
- - ">="
|
|
100
|
+
- !ruby/object:Gem::Version
|
|
101
|
+
version: '3.0'
|
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
|
+
requirements:
|
|
104
|
+
- - ">="
|
|
105
|
+
- !ruby/object:Gem::Version
|
|
106
|
+
version: '0'
|
|
107
|
+
requirements: []
|
|
108
|
+
rubygems_version: 3.4.18
|
|
109
|
+
signing_key:
|
|
110
|
+
specification_version: 4
|
|
111
|
+
summary: Rails adapter for placet — declarative per-action authorization and ActiveRecord
|
|
112
|
+
scope composition
|
|
113
|
+
test_files: []
|