eaco 0.5.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.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +18 -0
  5. data/.yardopts +1 -0
  6. data/Appraisals +22 -0
  7. data/Gemfile +4 -0
  8. data/Guardfile +34 -0
  9. data/LICENSE.txt +23 -0
  10. data/README.md +225 -0
  11. data/Rakefile +26 -0
  12. data/eaco.gemspec +27 -0
  13. data/features/active_record.example.yml +8 -0
  14. data/features/active_record.travis.yml +7 -0
  15. data/features/rails_integration.feature +10 -0
  16. data/features/step_definitions/database.rb +7 -0
  17. data/features/step_definitions/resource_authorization.rb +15 -0
  18. data/features/support/env.rb +9 -0
  19. data/gemfiles/rails_3.2.gemfile +9 -0
  20. data/gemfiles/rails_4.0.gemfile +8 -0
  21. data/gemfiles/rails_4.1.gemfile +8 -0
  22. data/gemfiles/rails_4.2.gemfile +8 -0
  23. data/lib/eaco.rb +93 -0
  24. data/lib/eaco/acl.rb +206 -0
  25. data/lib/eaco/actor.rb +86 -0
  26. data/lib/eaco/adapters.rb +14 -0
  27. data/lib/eaco/adapters/active_record.rb +70 -0
  28. data/lib/eaco/adapters/active_record/compatibility.rb +83 -0
  29. data/lib/eaco/adapters/active_record/compatibility/v32.rb +27 -0
  30. data/lib/eaco/adapters/active_record/compatibility/v40.rb +59 -0
  31. data/lib/eaco/adapters/active_record/compatibility/v41.rb +16 -0
  32. data/lib/eaco/adapters/active_record/compatibility/v42.rb +17 -0
  33. data/lib/eaco/adapters/active_record/postgres_jsonb.rb +36 -0
  34. data/lib/eaco/adapters/couchrest_model.rb +37 -0
  35. data/lib/eaco/adapters/couchrest_model/couchdb_lucene.rb +71 -0
  36. data/lib/eaco/controller.rb +158 -0
  37. data/lib/eaco/cucumber.rb +11 -0
  38. data/lib/eaco/cucumber/active_record.rb +163 -0
  39. data/lib/eaco/cucumber/active_record/department.rb +19 -0
  40. data/lib/eaco/cucumber/active_record/document.rb +18 -0
  41. data/lib/eaco/cucumber/active_record/position.rb +21 -0
  42. data/lib/eaco/cucumber/active_record/schema.rb +36 -0
  43. data/lib/eaco/cucumber/active_record/user.rb +24 -0
  44. data/lib/eaco/cucumber/world.rb +136 -0
  45. data/lib/eaco/designator.rb +264 -0
  46. data/lib/eaco/dsl.rb +40 -0
  47. data/lib/eaco/dsl/acl.rb +163 -0
  48. data/lib/eaco/dsl/actor.rb +139 -0
  49. data/lib/eaco/dsl/actor/designators.rb +110 -0
  50. data/lib/eaco/dsl/base.rb +52 -0
  51. data/lib/eaco/dsl/resource.rb +129 -0
  52. data/lib/eaco/dsl/resource/permissions.rb +131 -0
  53. data/lib/eaco/error.rb +36 -0
  54. data/lib/eaco/railtie.rb +46 -0
  55. data/lib/eaco/rake.rb +10 -0
  56. data/lib/eaco/rake/default_task.rb +164 -0
  57. data/lib/eaco/resource.rb +234 -0
  58. data/lib/eaco/version.rb +7 -0
  59. data/spec/eaco/acl_spec.rb +147 -0
  60. data/spec/eaco/actor_spec.rb +13 -0
  61. data/spec/eaco/adapters/active_record/postgres_jsonb_spec.rb +9 -0
  62. data/spec/eaco/adapters/active_record_spec.rb +13 -0
  63. data/spec/eaco/adapters/couchrest_model/couchdb_lucene_spec.rb +9 -0
  64. data/spec/eaco/adapters/couchrest_model_spec.rb +9 -0
  65. data/spec/eaco/controller_spec.rb +12 -0
  66. data/spec/eaco/designator_spec.rb +25 -0
  67. data/spec/eaco/dsl/acl_spec.rb +9 -0
  68. data/spec/eaco/dsl/actor/designators_spec.rb +7 -0
  69. data/spec/eaco/dsl/actor_spec.rb +15 -0
  70. data/spec/eaco/dsl/resource/permissions_spec.rb +7 -0
  71. data/spec/eaco/dsl/resource_spec.rb +17 -0
  72. data/spec/eaco/error_spec.rb +9 -0
  73. data/spec/eaco/resource_spec.rb +31 -0
  74. data/spec/eaco_spec.rb +49 -0
  75. data/spec/spec_helper.rb +71 -0
  76. metadata +296 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e72095b7ec920c9b83c284fa3c7331253733bbc8
4
+ data.tar.gz: 40f6b7c39dc3796bf3495f57d7f4708d233037f4
5
+ SHA512:
6
+ metadata.gz: a8834f93d09048dad12cb0afd5dcae646b8dccb73c193320e6a9eb1bb4a7292b642ef0a02ec9db437616d8ecda44295237853b849138a9157d6e59af8fe7945b
7
+ data.tar.gz: f107e5cef842ee26018c0fd148ae9ea4d4d91a64f49763b892c56ffe108ee6cc30276661254dadca5b3297c3bf83ce1b7a3075b0ff92ae8411952a1423281994
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ gemfiles/*.gemfile.lock
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ features/active_record.yml
12
+ features/active_record.log
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ tmp
17
+ *.bundle
18
+ *.so
19
+ *.o
20
+ *.a
21
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,18 @@
1
+ rvm:
2
+ - 2.0.0
3
+ - 2.1.5
4
+ - 2.2.0
5
+
6
+ gemfile:
7
+ - gemfiles/rails_3.2.gemfile
8
+ - gemfiles/rails_4.0.gemfile
9
+ - gemfiles/rails_4.1.gemfile
10
+ - gemfiles/rails_4.2.gemfile
11
+
12
+ addons:
13
+ postgresql: "9.4"
14
+
15
+ before_script:
16
+ - psql -c "CREATE DATABASE eaco;" -U postgres
17
+
18
+ script: bundle exec rake EACO_AR_CONFIG=./features/active_record.travis.yml
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --protected --private --no-private --hide-void-return '{lib,features/support}/**/*.rb' - README.md LICENSE.txt
data/Appraisals ADDED
@@ -0,0 +1,22 @@
1
+ # Test against 3.2 -> 4.2
2
+ #
3
+ appraise 'rails-3.2' do
4
+ gem 'rails', '~> 3.2.0'
5
+ gem 'pg'
6
+ gem 'activerecord-postgres-json'
7
+ end
8
+
9
+ appraise 'rails-4.0' do
10
+ gem 'rails', '~> 4.0.0'
11
+ gem 'pg'
12
+ end
13
+
14
+ appraise 'rails-4.1' do
15
+ gem 'rails', '~> 4.1.0'
16
+ gem 'pg'
17
+ end
18
+
19
+ appraise 'rails-4.2' do
20
+ gem 'rails', '~> 4.2.0'
21
+ gem 'pg'
22
+ end
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in eaco.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,34 @@
1
+ # Eaco's Guardfile
2
+
3
+ # Watch lib/ and spec/
4
+ directories %w(lib spec)
5
+
6
+ # Clear the screen before every task
7
+ clearing :on
8
+
9
+ guard :rspec, version: 3, cmd: 'rspec' do
10
+ # When single specs change, run them.
11
+ watch(%r{^spec/.+_spec\.rb$})
12
+
13
+ # When spec_helper changes rerun all the specs.
14
+ watch('spec/spec_helper.rb') { "spec" }
15
+
16
+ # When a source changes run its unit spec.
17
+ watch(%r{^lib/(.+)\.rb$}) {|m| "spec/#{m[1]}_spec.rb"
18
+ end
19
+
20
+ guard :cucumber do
21
+ # When single features change, run them.
22
+ watch(%r{^features/.+\.feature$})
23
+
24
+ # When support code changes, rerun all features.
25
+ watch(%r{^features/support/.+$}) { 'features' }
26
+
27
+ # When a step definition for a feature changes, rerun the corresponding feature.
28
+ watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
29
+ end
30
+
31
+ guard :shell do
32
+ # Rerun scenarios when source code changes
33
+ watch(%r{^lib/.+\.rb$}) { 'cucumber' }
34
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2013-2015 IFAD
2
+ Copyright (c) 2013-2015 Marcello Barnaba <m.barnaba@ifad.org>
3
+
4
+ MIT License
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,225 @@
1
+ # Eaco
2
+
3
+ [![Build Status](https://travis-ci.org/ifad/eaco.svg)](https://travis-ci.org/ifad/eaco) *currently writing specs*
4
+ [![Code Climate](https://codeclimate.com/github/ifad/eaco/badges/gpa.svg)](https://codeclimate.com/github/ifad/eaco)
5
+ [![Inline docs](http://inch-ci.org/github/ifad/eaco.svg?branch=master)](http://inch-ci.org/github/ifad/eaco/master)
6
+
7
+ Eacus, the holder of the keys of Hades, is an ACL-based authorization
8
+ framework for Ruby.
9
+
10
+ ![Eaco e Telamone][eaco-e-telamone]
11
+
12
+ ## Design
13
+
14
+ Eaco provides your context's Resources discretionary access by an Actor.
15
+ Access to the Resource is determined using an ACL.
16
+
17
+ Different Actors can have different levels of access to the same Resource,
18
+ depending on their role as determined by the ACL.
19
+
20
+ To each role are granted a set of possible abilities, and access is verified
21
+ by checking whether a given actor can perform a specific ability.
22
+
23
+ Actors are described by their Designators, a pluggable mechanism to be
24
+ implemented in your application.
25
+
26
+ Each Actor has many designators that describe either its identity or its
27
+ belonging to a group or occupying a position in a department.
28
+
29
+ Designators are Ruby classes that can embed any sort of custom behaviour that
30
+ your application requires.
31
+
32
+ ACLs are hashes with designators as keys and roles as values. Extracting
33
+ authorized collections requires only an hash key lookup mechanism in your
34
+ database. Adapters are provided for PG's jsonb and for CouchDB-Lucene.
35
+
36
+ ## Installation
37
+
38
+ Add this line to your application's Gemfile:
39
+
40
+ gem 'eaco', github: 'ifad/eaco'
41
+
42
+ And then execute:
43
+
44
+ $ bundle
45
+
46
+ ## Usage
47
+
48
+ Create `config/authorization.rb` [(rdoc)](http://www.rubydoc.info/github/ifad/eaco/master/Eaco/DSL)
49
+
50
+ ```ruby
51
+ # Defines `Document` to be an authorized resource.
52
+ #
53
+ # Adds Document.accessible_by and Document#allows
54
+ #
55
+ authorize Document, using: :lucene do
56
+ roles :owner, :editor, :reader
57
+
58
+ permissions do
59
+ reader :read
60
+ editor reader, :edit
61
+ owner editor, :destroy
62
+ end
63
+ end
64
+
65
+ # Defines an actor and the sources from which the
66
+ # designators are harvested.
67
+ #
68
+ # Adds User#designators
69
+ #
70
+ actor User do
71
+ admin do |user|
72
+ user.admin?
73
+ end
74
+
75
+ designators do
76
+ user from: :id
77
+ group from: :groups
78
+ tag from: :tags
79
+ end
80
+ end
81
+ ```
82
+
83
+ Given a Resource [(rdoc)](http://www.rubydoc.info/github/ifad/eaco/master/Eaco/Resource)
84
+ with an ACL [(rdoc)](http://www.rubydoc.info/github/ifad/eaco/master/Eaco/ACL):
85
+
86
+ ```ruby
87
+ # An example ACL
88
+ >> document = Document.first
89
+ => #<Document id:42 name:"President's report for loans.docx" [...]>
90
+ >> document.acl
91
+ => #<Document::ACL {"user:10" => :owner, "group:reviewers" => :reader}>
92
+ ```
93
+
94
+ and an Actor [(rdoc)](http://www.rubydoc.info/github/ifad/eaco/master/Eaco/Actor):
95
+
96
+ ```ruby
97
+ # An example Actor
98
+ >> user = User.find(10)
99
+ => #<User id:10 name:"Bob Fropp" group_ids:['employees'], tags:['english']>
100
+ >> user.designators
101
+ => #<Set{ #<Designator(User) value:10>, #<Designator(Group) value:"employees">, #<Designator(Tag) value:"english"> }
102
+ ```
103
+
104
+ you can check if the Actor can perform a specific action on the Resource:
105
+
106
+ ```ruby
107
+ >> user.can? :read, document
108
+ => true
109
+
110
+ >> document.allows? :read, user
111
+ => true
112
+ ```
113
+
114
+ and which access level (`role`) the Actor has for this Resource:
115
+
116
+ ```ruby
117
+ >> document.role_of user
118
+ => :owner
119
+
120
+ >> boss = User.find_by_group('reviewer').first
121
+ => #<User id:42 name:"Jake Leister" group_ids:['reviewers', 'bosses']>
122
+
123
+ >> document.role_of boss
124
+ => :reader
125
+
126
+ >> boss.can? :read, document
127
+ => true
128
+
129
+ >> boss.can? :destroy, document
130
+ => false
131
+
132
+ >> user.can? :destroy, document
133
+ => true
134
+ ```
135
+
136
+ Grant reader access to a specific user:
137
+
138
+ ```ruby
139
+ >> user
140
+ => #<User id:42 name:"Bob Frop">
141
+
142
+ >> document.grant :reader, :user, user.id
143
+ => #<Document::ACL "user:42" => :reader>
144
+
145
+ >> user.can? :read, document
146
+ => true
147
+ ```
148
+
149
+ Grant reader access to a group:
150
+
151
+ ```ruby
152
+ >> user
153
+ => #<User id:42 groups:['reviewers']>
154
+
155
+ >> document.grant :reader, :group, 3
156
+ => #<Document::ACL "group:reviewers" => :reader>
157
+
158
+ >> user.can? :read, document
159
+ => true
160
+
161
+ >> document.allows? :read, user
162
+ => true
163
+ ```
164
+
165
+ Obtain a collection of Resources accessible by a given Actor [(rdoc)](http://www.rubydoc.info/github/ifad/eaco/master/Eaco/Adapters):
166
+
167
+ ```ruby
168
+ >> Document.accessible_by(user)
169
+ ```
170
+
171
+ Check whether a controller action can be accessed by an user. Your
172
+ `ApplicationController` must respond to `current_user` for this to work.
173
+ [(rdoc)](http://www.rubydoc.info/github/ifad/eaco/master/Eaco/Controller)
174
+
175
+ ```ruby
176
+ class DocumentsController < ApplicationController
177
+ before_filter :find_document
178
+
179
+ authorize :edit, :update, [:document, :read]
180
+
181
+ private
182
+ def find_document
183
+ @document = Document.find(:id)
184
+ end
185
+ end
186
+ ```
187
+
188
+ ## Running specs
189
+
190
+ You need a running postgresql 9.4 instance.
191
+
192
+ Create an user and a database:
193
+
194
+ $ sudo -u postgres psql
195
+
196
+ postgres=# CREATE ROLE eaco LOGIN;
197
+ CREATE ROLE
198
+
199
+ postgres=# CREATE DATABASE eaco OWNER eaco ENCODING 'utf8';
200
+ CREATE DATABASE
201
+
202
+ postgres=# ^D
203
+
204
+ Create `features/active_record.yml` with your database configuration,
205
+ see `features/active_record.example.yml` for an example.
206
+
207
+ Run `bundle` once. This will install the base bundle.
208
+
209
+ Run `appraisal` once. This will install the supported Rails versions and pg.
210
+
211
+ Run `rake`. This will run the specs and cucumber features.
212
+
213
+ Specs are run against the supported rails versions in turn. If you want to
214
+ focus on a single release, use `appraisal rails-X.Y rake`, where `X.Y` can be
215
+ `3.2`, `4.0`, `4.1` or `4.2`.
216
+
217
+ ## Contributing
218
+
219
+ 1. Fork it ( https://github.com/ifad/eaco/fork )
220
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
221
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
222
+ 4. Push to the branch (`git push origin my-new-feature`)
223
+ 5. Create a new Pull Request
224
+
225
+ [eaco-e-telamone]: http://upload.wikimedia.org/wikipedia/commons/7/70/Aeacus_telemon.jpg "Aeacus telemon by user Ravenous at en.wikipedia.org - Public domain through Wikimedia Commons - http://commons.wikimedia.org/wiki/File:Aeacus_telemon.jpg#mediaviewer/File:Aeacus_telemon.jpg"
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ # Bundler
2
+ require 'bundler/setup'
3
+ require 'bundler/gem_tasks'
4
+
5
+ # YARD
6
+ require 'yard'
7
+ YARD::Rake::YardocTask.new
8
+
9
+ # RSpec
10
+ require 'rspec/core/rake_task'
11
+ RSpec::Core::RakeTask.new
12
+
13
+ # Appraisal
14
+ require 'appraisal/task'
15
+ Appraisal::Task.new
16
+
17
+ # Cucumber
18
+ require 'cucumber'
19
+ require 'cucumber/rake/task'
20
+ Cucumber::Rake::Task.new
21
+
22
+ # Our default rake task
23
+ require 'eaco/rake'
24
+ Eaco::Rake::DefaultTask.new
25
+
26
+ # Thanks for reading.
data/eaco.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'eaco/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "eaco"
8
+ spec.version = Eaco::VERSION
9
+ spec.authors = ["Marcello Barnaba"]
10
+ spec.email = ["vjt@openssl.it"]
11
+ spec.summary = %q{Authorization framework}
12
+ spec.homepage = "https://github.com/ifad/eaco"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ [
21
+ ["bundler", "~> 1.6"],
22
+ "rake", "byebug", "guard", "yard", "appraisal",
23
+ "rspec", "guard-rspec", "yard-rspec",
24
+ "cucumber", "guard-cucumber"
25
+
26
+ ].each {|gem| spec.add_development_dependency *gem }
27
+ end
@@ -0,0 +1,8 @@
1
+ # PostgreSQL 9.4 and up is required.
2
+ #
3
+ adapter: "postgresql"
4
+ database: "eaco"
5
+ username: "aecus"
6
+ password: "theGreat!"
7
+ encoding: "utf8"
8
+ hostname: "localhost"
@@ -0,0 +1,7 @@
1
+ # PostgreSQL 9.4 and up is required.
2
+ #
3
+ adapter: "postgresql"
4
+ hostname: "localhost"
5
+ database: "eaco"
6
+ username: "postgres"
7
+ password: ""