eaco 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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: ""