discretion 0.4.0.pre.alpha → 1.0.0.pre.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rspec +2 -0
- data/README.md +4 -2
- data/Rakefile +4 -1
- data/discretion.gemspec +6 -0
- data/lib/discretion.rb +1 -1
- data/lib/discretion/can.rb +6 -4
- data/lib/discretion/current_viewer.rb +3 -0
- data/lib/discretion/discreet_model.rb +5 -1
- data/lib/discretion/helpers.rb +22 -2
- data/lib/discretion/railtie.rb +2 -0
- data/lib/discretion/version.rb +1 -1
- metadata +87 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a56b9cc6109e4904c4c4ffa1569af797b4e043a7
|
4
|
+
data.tar.gz: 77a3f57cd1628eee0ed41ca2ae4c71f032309829
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2ec9587ef19c98cd89b9ed107c16907a9a7c3fe1316f58b86b6ac66e38c4bef621c959e1286d2f04466e6b4dea1168e12a8e20959b8b33a5395eaa9816c2bd7a
|
7
|
+
data.tar.gz: e3b5fcad23ef87209535356e5ea6d5c4c9d2bc3d60d4cc722c1a772ab05e92a420a6d4cb74fc2d87adcca341b44d61b80d44e2b13fa3db736d3b85ef88f89c01
|
data/.gitignore
CHANGED
data/.rspec
ADDED
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Discretion
|
2
2
|
|
3
|
+
**tldr; Discretion is a simple privacy/authorization framework for Rails projects. You define `can_see?(viewer)` methods in a model class to determine if a given viewer is allowed to view/load/read the model (record). If so, you can query and load the record as you normally would in Rails (e.g. using `find`, `where`, `limit`, ...). If not, then Discretion will throw an exception when you try to fetch the record. Something similar is done for writes as well.**
|
4
|
+
|
3
5
|
## Installation
|
4
6
|
|
5
7
|
Add this line to your application's Gemfile:
|
@@ -25,7 +27,7 @@ Or install it yourself as:
|
|
25
27
|
|
26
28
|
The idea is simple: we colocate the read and write policies with the model definitions themselves by defining `can_see?(viewer)` and optionally `can_write?(viewer)`. The semantics are straightforward: given a `viewer` (typically a `User` but can be anything you want -- more on this below), can that viewer see the record encapsulated by the model class?
|
27
29
|
|
28
|
-
For example, let's say we have a web app for a large non-profit organization which has staff who have to raise money from donors. So we might have models like `Donor`, `Staff`, and `Donation
|
30
|
+
For example, let's say we have a web app for a large non-profit organization which has staff who have to raise money from donors. So we might have models like `Donor`, `Staff`, and `Donation`. Below we will describe how we would set up authorization/privacy policies for these models using Discretion.
|
29
31
|
|
30
32
|
### Opt-In
|
31
33
|
|
@@ -185,7 +187,7 @@ Discretion is totally opaque and should not require any changes in how you query
|
|
185
187
|
|
186
188
|
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
187
189
|
|
188
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
190
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
189
191
|
|
190
192
|
## Contributing
|
191
193
|
|
data/Rakefile
CHANGED
data/discretion.gemspec
CHANGED
@@ -14,6 +14,7 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.homepage = 'https://github.com/abeland/discretion'
|
15
15
|
spec.license = 'MIT'
|
16
16
|
|
17
|
+
spec.add_dependency 'activesupport'
|
17
18
|
spec.add_dependency 'rails', '~>5'
|
18
19
|
spec.add_dependency 'request_store', '~>1.3'
|
19
20
|
spec.required_ruby_version = '>= 2.2.2'
|
@@ -25,6 +26,11 @@ Gem::Specification.new do |spec|
|
|
25
26
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
27
|
spec.require_paths = ['lib']
|
27
28
|
|
29
|
+
spec.add_development_dependency 'activerecord'
|
28
30
|
spec.add_development_dependency 'bundler', '~> 1.15'
|
31
|
+
spec.add_development_dependency 'factory_bot_rails'
|
29
32
|
spec.add_development_dependency 'rake', '~> 10.0'
|
33
|
+
spec.add_development_dependency 'rspec'
|
34
|
+
spec.add_development_dependency 'rspec-rails'
|
35
|
+
spec.add_development_dependency 'sqlite3'
|
30
36
|
end
|
data/lib/discretion.rb
CHANGED
@@ -5,7 +5,7 @@ require 'discretion/errors'
|
|
5
5
|
require 'discretion/helpers'
|
6
6
|
require 'discretion/meta'
|
7
7
|
require 'discretion/middleware'
|
8
|
-
require 'discretion/railtie'
|
8
|
+
require 'discretion/railtie' if defined?(Rails)
|
9
9
|
require 'discretion/version'
|
10
10
|
|
11
11
|
ActiveRecord::Base.send(:include, Discretion::Meta) if defined?(ActiveRecord)
|
data/lib/discretion/can.rb
CHANGED
@@ -2,6 +2,7 @@ module Discretion
|
|
2
2
|
class << self
|
3
3
|
def can_see_record?(viewer, record)
|
4
4
|
return true unless record.is_a?(Discretion::DiscreetModel)
|
5
|
+
return true if Discretion::OMNISCIENT_VIEWER == viewer || Discretion::OMNIPOTENT_VIEWER == viewer
|
5
6
|
|
6
7
|
record.send(:can_see?, viewer)
|
7
8
|
end
|
@@ -10,16 +11,17 @@ module Discretion
|
|
10
11
|
can_see_record?(Discretion.current_viewer, record)
|
11
12
|
end
|
12
13
|
|
13
|
-
def can_write_record?(viewer, record)
|
14
|
+
def can_write_record?(viewer, record, changes, new_record)
|
14
15
|
return true unless record.is_a?(Discretion::DiscreetModel)
|
16
|
+
return true if Discretion::OMNIPOTENT_VIEWER == viewer
|
15
17
|
|
16
18
|
record.respond_to?(:can_write?, true) ?
|
17
|
-
record.send(:can_write?, viewer) :
|
19
|
+
record.send(:can_write?, viewer, changes, new_record) :
|
18
20
|
can_see_record?(viewer, record)
|
19
21
|
end
|
20
22
|
|
21
|
-
def current_viewer_can_write_record?(record)
|
22
|
-
can_write_record?(Discretion.current_viewer, record)
|
23
|
+
def current_viewer_can_write_record?(record, changes, new_record)
|
24
|
+
can_write_record?(Discretion.current_viewer, record, changes, new_record)
|
23
25
|
end
|
24
26
|
end
|
25
27
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
1
3
|
module Discretion
|
2
4
|
module DiscreetModel
|
3
5
|
extend ActiveSupport::Concern
|
@@ -8,7 +10,9 @@ module Discretion
|
|
8
10
|
end
|
9
11
|
|
10
12
|
before_save do |record|
|
11
|
-
|
13
|
+
unless Discretion.current_viewer_can_write_record?(record, changes, new_record?)
|
14
|
+
raise Discretion::CannotWriteError
|
15
|
+
end
|
12
16
|
end
|
13
17
|
end
|
14
18
|
end
|
data/lib/discretion/helpers.rb
CHANGED
@@ -12,8 +12,28 @@ module Discretion
|
|
12
12
|
records.all? { |record| Discretion.can_see_record?(viewer, record) }
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
|
15
|
+
def omnisciently
|
16
|
+
# Calling Proc.new will create a Proc from the implicitly given block to
|
17
|
+
# the current method.
|
18
|
+
# cf. http://ruby-doc.org/core-2.5.0/Proc.html#method-c-new
|
19
|
+
with_viewer(Discretion::OMNISCIENT_VIEWER, &Proc.new)
|
20
|
+
end
|
21
|
+
|
22
|
+
def omnipotently
|
23
|
+
# Calling Proc.new will create a Proc from the implicitly given block to
|
24
|
+
# the current method.
|
25
|
+
# cf. http://ruby-doc.org/core-2.5.0/Proc.html#method-c-new
|
26
|
+
with_viewer(Discretion::OMNIPOTENT_VIEWER, &Proc.new)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def with_viewer(viewer)
|
32
|
+
orig_viewer = Discretion.current_viewer
|
33
|
+
Discretion.set_current_viewer(viewer)
|
34
|
+
yield
|
35
|
+
ensure
|
36
|
+
Discretion.set_current_viewer(orig_viewer)
|
17
37
|
end
|
18
38
|
end
|
19
39
|
end
|
data/lib/discretion/railtie.rb
CHANGED
data/lib/discretion/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: discretion
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.pre.alpha
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Abe Land
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-02-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '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'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rails
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +52,20 @@ dependencies:
|
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activerecord
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
41
69
|
- !ruby/object:Gem::Dependency
|
42
70
|
name: bundler
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +80,20 @@ dependencies:
|
|
52
80
|
- - "~>"
|
53
81
|
- !ruby/object:Gem::Version
|
54
82
|
version: '1.15'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: factory_bot_rails
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
55
97
|
- !ruby/object:Gem::Dependency
|
56
98
|
name: rake
|
57
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +108,48 @@ dependencies:
|
|
66
108
|
- - "~>"
|
67
109
|
- !ruby/object:Gem::Version
|
68
110
|
version: '10.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rspec-rails
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: sqlite3
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
69
153
|
description: A simple privacy/authorization framework for Rails projects.
|
70
154
|
email:
|
71
155
|
- codeclimbcoffee@gmail.com
|
@@ -74,6 +158,7 @@ extensions: []
|
|
74
158
|
extra_rdoc_files: []
|
75
159
|
files:
|
76
160
|
- ".gitignore"
|
161
|
+
- ".rspec"
|
77
162
|
- CODE_OF_CONDUCT.md
|
78
163
|
- Gemfile
|
79
164
|
- LICENSE.txt
|