77 Commits
1.6.5 ... 1.6.8

Author SHA1 Message Date
Ryan Bates
1e89b31bad releasing 1.6.8 2012-06-25 16:17:32 -07:00
Ryan Bates
5f1be25419 preparing for 1.6.8 2012-06-19 12:56:51 -07:00
Ryan Bates
6d7bce78fc updating changelog 2012-06-19 11:58:59 -07:00
Ryan Bates
a0200166cc removing project status section from readme since contributors are now kind enough to keep tabs on the issue tracker 2012-06-19 11:37:45 -07:00
Ryan Bates
112a995327 clearing leftover whitespace 2012-06-19 11:36:59 -07:00
Ryan Bates
944804183e load ostruct for OpenStruct used in spec 2012-06-19 11:35:58 -07:00
Ryan Bates
2b89dbbdfa Merge pull request #653 from andhapp/fix-pull-request-640
Init attributes in InheritedResources controller w/ specs
2012-06-19 10:53:22 -07:00
Ryan Bates
aff8ca60e4 Merge pull request #650 from andhapp/fix-pull-request-486
Fixes Nested Resource Loading
2012-06-19 10:50:29 -07:00
Ryan Bates
33e33c584e Merge pull request #618 from spatil/master
Check for defined ActionController::Base instead ActionController
2012-06-19 10:41:14 -07:00
Anuj Dutta
a1254ca1c6 Fix pull request 640. For some reason github didn't allow a clean merge althought there weren't any conflicts. Fix it so that it's easier to just merge via the UI. 2012-06-19 00:13:19 +01:00
Mike Pack
88aba4664a Refactor out attribute assignment 2012-06-19 00:08:27 +01:00
Mike Pack
b965f5bab4 Add specs for resource attributes.
Remove inconsistent line breaks.
2012-06-19 00:08:27 +01:00
mccraig mccraig of the clan mccraig
c2c0b86c3a initialise attributes after a resource is created by an InheritedResources controller 2012-06-19 00:08:26 +01:00
Mark Sim
d5baed6281 Fixes Nested Resource Loading 2012-06-18 06:52:32 +01:00
Ryan Bates
7bf683d8f4 Merge pull request #645 from andhapp/issue-644
Allow users to specify a mix of can and cannot rule for mongoid
2012-06-11 09:52:38 -07:00
Anuj Dutta
da663aaed1 Fix for issue-644 to allow users to specify a mix of can and cannot rules with mongo. 2012-06-10 22:54:45 +01:00
Ryan Bates
80a8c39a93 Merge pull request #632 from andhapp/fix-issue-327
Fix to handle MetaWhere and non-MetaWhere conditions correctly.
2012-05-29 10:04:18 -07:00
Ryan Bates
b3f9ffe93b Merge pull request #625 from rogercampos/merging
Adding Ability#merge
2012-05-28 11:02:51 -07:00
Anuj Dutta
c27ead5b9f Fix to handle MetaWhere and non-MetaWhere conditions correctly. 2012-05-26 18:00:50 +01:00
Ryan Bates
0c21831b4d Merge pull request #619 from derekprior/namespace-fix
Updated: port fix for namespaced params from 2.0 back to 1.6
2012-05-14 09:24:25 -07:00
Chris Gunther
b347c7b78c port fix for namespaced params from 2.0 back to 1.6 2012-05-14 10:52:29 -04:00
Ryan Bates
1cdd7b3c18 Merge pull request #509 from moffff/master
Fix 'spec/spec_helper.rb:20: uninitialized constant WithModel (NameError)'
2012-05-11 08:59:41 -07:00
Ryan Bates
7f4f469e58 Merge pull request #492 from soopa/master
Fix "uninitialized constant CanCan::Rule::ModelAdapters"
2012-05-11 08:51:50 -07:00
Gimi Liang
14e1f5cad4 Merge pull request #535 from manuelmeurer/patch-2
Fixed a small typo
2012-05-11 08:17:55 -07:00
Gimi Liang
8e46ccad8c Merge pull request #616 from NickClark/rails_2_3_readme_clarification
Clarify readme for rails 2.3 users
2012-05-11 08:12:22 -07:00
Nicholas Clark
0bbe2e1802 Clarify readme for rails 2.3 users 2012-05-10 19:03:51 -04:00
Ryan Bates
10cbfbb923 adding a .rbenv-version file 2012-05-10 14:24:13 -07:00
Ryan Bates
a8a85f13a3 Merge pull request #541 from icrowley/master
Fixed bug with params for actions that build new instances with namespaced models
2012-05-10 13:51:45 -07:00
Ryan Bates
c1f7181336 Merge pull request #505 from nertzy/update_with_model
Use latest with_model gem
2012-05-10 11:45:27 -07:00
Ryan Bates
70515de8c1 Merge pull request #556 from mauriciozaffari/master
Pass forward :if and :unless options to the before filter.
2012-05-10 11:00:32 -07:00
Ryan Bates
b73bd062a8 Merge pull request #564 from flop/master
False positives on multiple nested abilities definitions
2012-05-10 10:59:08 -07:00
Ryan Bates
d1176245e6 Merge pull request #559 from plentz/patch-1
Adding travis-ci badge
2012-05-10 10:47:13 -07:00
Ryan Bates
78e1a17258 Merge pull request #587 from route/patch-1
Just add singleton to description of authorize_resource
2012-05-10 09:27:03 -07:00
Ryan Bates
6e8bc851be Merge pull request #607 from Mixbook/master
Added support for value to be Enumerable
2012-05-10 09:25:59 -07:00
Aryk Grosz
65bbf0e354 Add check for Enumerable as condition value 2012-04-23 00:51:55 -07:00
Ryan Bates
aed37cda03 adding project status message to readme 2012-04-17 14:00:30 -07:00
Shailesh Patil
51702e0f7b checked for ActionContoller::Base instead of just ActionContoller 2012-04-03 15:44:41 +05:30
Dmitriy Vorotilin
f166b5945a Just add singleton to description of authorize_resource 2012-03-23 01:34:04 +04:00
Florent Piteau
ba01349eb0 Don't remove key-value from the subject hash we might want to use it again. 2012-02-29 15:49:19 +01:00
Diego Plentz
37a42e3666 adding travis-ci badge 2012-02-14 23:41:18 -02:00
Mauricio Zaffari
83e2dcebd0 Pass forward :if and :unless options to the before filter. i.e:
load_and_authorize_resource :if => condition == true
2012-02-02 21:06:38 -02:00
Dmitry Afanasyev
baadcb923b Fixed bug with params for actions that build new instances with namespaced models 2012-01-06 01:21:11 +04:00
Manuel Meurer
e65f9bd4fd Fixed typo 2011-12-25 19:55:35 +01:00
Artem Kornienko
f18f53c9ce Fixed problem with 'with_model' gem in DataMapper tests and Mongoid tests. 2011-11-09 18:38:19 +02:00
Grant Hutchins
98312940e4 Use latest with_model gem
Now with_model clears the association class cache
between specs, which fixes a test pollution
problem.
2011-11-02 22:37:37 -04:00
Roger Campos
7797b37c7e Adding Ability#merge 2011-10-31 14:08:50 +01:00
soopa
80ceaf8e17 fix uninitialized constant warning in CanCan::Rule#model_adapter 2011-10-14 20:06:43 -05:00
Ryan Bates
9eebeb2155 releasing 1.6.7 with nested resource fix 2011-10-04 15:04:28 -07:00
Ryan Bates
67a3038628 quick fix to get nested resources working again - closes #482 2011-10-04 15:02:59 -07:00
Ryan Bates
26b40f2b49 releasing version 1.6.6 2011-09-28 17:00:32 -07:00
Ryan Bates
98326394f0 removing jruby/rubinius from travis.yml for now until I figure out why they aren't passing 2011-09-28 16:24:03 -07:00
Patrick Morgan
b3fc5add34 Correct "return cant jump across threads" error when using check_authorization() 2011-09-28 16:05:38 -07:00
Ryan Bates
610d7e3ec4 Merge pull request #425 from skhisma/master
Allow custom IDs to be specified when calling load_resource
2011-09-28 13:44:19 -07:00
Ryan Bates
cfb801ed8d Merge pull request #424 from whilefalse/master
Support for namespaced models and engines
2011-09-28 13:34:30 -07:00
Ryan Bates
0edd310c41 Merge pull request #476 from kirkconnell/with_model-version-fix
Specs fail when running in a freshly installed environment.
2011-09-28 11:57:17 -07:00
kirkconnell
5ab7dea2f0 use version 1.x of with_model to avoid errors in class comparisons 2011-09-20 18:43:39 -06:00
Ryan Bates
916f97fbf3 updating Rails gem dev dependency 2011-07-23 19:53:18 -07:00
Ryan Bates
2be3f98e11 removing 1.9.2 from .travis.yml 2011-07-23 19:33:43 -07:00
Ryan Bates
0343f8f0b5 Merge pull request #427 from bai/master
Add .travis.yml for building cancan on a lovely Travis CI service
2011-07-23 19:31:45 -07:00
Ryan Bates
987dce0dc2 Merge pull request #421 from amc-projects/master
Compatibility fix for rspec-instafail and rspec1
2011-07-23 14:46:37 -07:00
Ryan Bates
e0492f5d75 Merge pull request #426 from manuelmeurer/patch-1
Fixed documentation for skip_load_resource and skip_authorize_resource.
2011-07-23 13:31:03 -07:00
beawesomeinstead
0fc67e4d56 These lines are defaults, should be fine this way 2011-07-21 17:02:12 +03:00
beawesomeinstead
d24ef454e0 Run rake instead of rake test 2011-07-21 15:48:20 +03:00
Manuel Meurer
e561532bab Fixed typos. 2011-07-21 05:12:09 -07:00
beawesomeinstead
1ab4e2d48c The first try to make cancan pass on Travis CI 2011-07-21 14:51:47 +03:00
Geoff Parsons
7937a282a3 :id_param option to load_resource allows specification of the param name to find members 2011-07-20 13:42:24 -04:00
Steven Anderson
d35419fa4c Added the needed camelize to recent patch for engines and namespaced models 2011-07-20 10:03:50 +01:00
Steven Anderson
6c497b8dd9 Added support for engines and namespaced models. 2011-07-20 09:31:53 +01:00
Michael MacDonald
3b33b36de9 Compatibility fix for using cancan with rspec-instafail and rspec1 2011-07-19 10:27:08 +10:00
Ryan Bates
600a3e16a5 Merge pull request #410 from psanford/improve_datamapper_loading
Load datamapper class methods via append_extensions.
2011-07-01 13:01:32 -07:00
psanford
ccd7a94d40 Load datamapper class methods via append_extensions.
This relaxes the previous requirement that cancan has to be loaded
before any models are. append_extensions will apply to all
previously loaded models as well as ones loaded after.
2011-07-01 12:48:20 -07:00
Ryan Bates
8f815c422a Merge pull request #409 from nhocki/patch-1
Make CanCan Default Message a translatable text.
2011-07-01 11:44:23 -07:00
Nicolás Hock Isaza
1c3e61725f Change the i18n default name to :"unauthorized.default" 2011-07-01 13:10:20 -05:00
Nicolás Hock Isaza
71f60bc4ac Adding tests for i18n translation for default messages 2011-06-30 18:16:47 -05:00
Nicolás Hock Isaza
596ad235a9 Make CanCan Default Message a translatable text. Default to the one you had. 2011-06-30 13:22:49 -07:00
Ryan Bates
613ab1c1ab delegating ControllerResource find to model adapter, uses 'get' for DataMapper - closes #373 2011-05-21 13:57:17 -07:00
Ryan Bates
c031f82dd2 allow :find_by option to be full find method name - closes #335 2011-05-19 23:37:36 -04:00
27 changed files with 422 additions and 48 deletions

1
.rbenv-version Normal file
View File

@@ -0,0 +1 @@
1.8.7-p357

7
.travis.yml Normal file
View File

@@ -0,0 +1,7 @@
rvm:
- 1.8.7
- ree
notifications:
recipients:
- graf.otodrakula@gmail.com
- ryan@railscasts.com

View File

@@ -1,3 +1,48 @@
1.6.8 (June 25, 2012)
* improved support for namespaced controllers and models
* pass :if and :unless options for load and authorize resource (thanks mauriciozaffari)
* Travis CI badge (thanks plentz)
* adding Ability#merge for combining multiple abilities (thanks rogercampos)
* support for multiple MetaWhere rules (thanks andhapp)
* various fixes for DataMapper, Mongoid, and Inherited Resource integration
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.7...1.6.8]
1.6.7 (October 4, 2011)
* fixing nested resource problem caused by namespace addition - issue #482
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.6...1.6.7]
1.6.6 (September 28, 2011)
* correct "return cant jump across threads" error when using check_authorization (thanks codeprimate) - issues #463, #469
* fixing tests in development by specifying with_model version (thanks kirkconnell) - issue #476
* added travis.yml file for TravisCI support (thanks bai) - issue #427
* better support for namespaced models (thanks whilefalse) - issues #424
* adding :id_param option to load_and_authorize_resource (thanks skhisma) - issue #425
* make default unauthorized message translatable text (thanks nhocki) - issue #409
* improving DataMapper behavior (thanks psanford, maxsum-corin) - issue #410, #373
* allow :find_by option to be full find method name - issue #335
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.5...1.6.6]
1.6.5 (May 18, 2011) 1.6.5 (May 18, 2011)
* pass action and subject through AccessDenied exception when :through isn't found - issue #366 * pass action and subject through AccessDenied exception when :through isn't found - issue #366
@@ -14,12 +59,15 @@
* improve scope merging - issue #328 * improve scope merging - issue #328
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.4...1.6.5]
1.6.4 (March 29, 2011) 1.6.4 (March 29, 2011)
* Fixed mongoid 'or' error - see issue #322 * Fixed mongoid 'or' error - see issue #322
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.3...1.6.4]
1.6.3 (March 25, 2011) 1.6.3 (March 25, 2011)
@@ -27,11 +75,15 @@
* Return subject passed to authorize! - see issue #314 * Return subject passed to authorize! - see issue #314
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.2...1.6.3]
1.6.2 (March 18, 2011) 1.6.2 (March 18, 2011)
* Fixed instance loading when :singleton option is used - see issue #310 * Fixed instance loading when :singleton option is used - see issue #310
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.1...1.6.2]
1.6.1 (March 15, 2011) 1.6.1 (March 15, 2011)
@@ -41,6 +93,8 @@
* Reverted Inherited Resources "collection" override since it doesn't seem to be working - see issue #305 * Reverted Inherited Resources "collection" override since it doesn't seem to be working - see issue #305
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.0...1.6.1]
1.6.0 (March 11, 2011) 1.6.0 (March 11, 2011)
@@ -62,6 +116,8 @@
* Raise an exception when trying to make a Ability condition with both a hash of conditions and a block - see issue #269 * Raise an exception when trying to make a Ability condition with both a hash of conditions and a block - see issue #269
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.5.1...1.6.0]
1.5.1 (January 20, 2011) 1.5.1 (January 20, 2011)
@@ -69,6 +125,8 @@
* Improving Mongoid support for multiple can and cannot definitions (thanks stellard) - see issue #239 * Improving Mongoid support for multiple can and cannot definitions (thanks stellard) - see issue #239
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.5.0...1.5.1]
1.5.0 (January 11, 2011) 1.5.0 (January 11, 2011)
@@ -90,6 +148,8 @@
* Internal: added .rvmrc to auto-switch to 1.8.7 with gemset - see issue #231 * Internal: added .rvmrc to auto-switch to 1.8.7 with gemset - see issue #231
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.4.1...1.5.0]
1.4.1 (November 12, 2010) 1.4.1 (November 12, 2010)
@@ -103,6 +163,8 @@
* Fix odd behavior when "cache_classes = false" (thanks mphalliday) - see issue #174 * Fix odd behavior when "cache_classes = false" (thanks mphalliday) - see issue #174
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.4.0...1.4.1]
1.4.0 (October 5, 2010) 1.4.0 (October 5, 2010)
@@ -142,11 +204,15 @@
* No longer calling block in +can+ definition when checking on class - see issue #116 * No longer calling block in +can+ definition when checking on class - see issue #116
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.3.4...1.4.0]
1.3.4 (August 31, 2010) 1.3.4 (August 31, 2010)
* Don't stop at +cannot+ with hash conditions when checking class (thanks tamoya) - see issue #131 * Don't stop at +cannot+ with hash conditions when checking class (thanks tamoya) - see issue #131
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.3.3...1.3.4]
1.3.3 (August 20, 2010) 1.3.3 (August 20, 2010)
@@ -154,16 +220,22 @@
* Pluralize nested associations for conditions in accessible_by (thanks mlooney) - see issue #123 * Pluralize nested associations for conditions in accessible_by (thanks mlooney) - see issue #123
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.3.2...1.3.3]
1.3.2 (August 7, 2010) 1.3.2 (August 7, 2010)
* Fixing slice error when passing in custom resource name - see issue #112 * Fixing slice error when passing in custom resource name - see issue #112
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.3.1...1.3.2]
1.3.1 (August 6, 2010) 1.3.1 (August 6, 2010)
* Fixing protected sanitize_sql error - see issue #111 * Fixing protected sanitize_sql error - see issue #111
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.3.0...1.3.1]
1.3.0 (August 6, 2010) 1.3.0 (August 6, 2010)
@@ -191,6 +263,8 @@
* Supporting deeply nested aliases - see issue #98 * Supporting deeply nested aliases - see issue #98
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.2.0...1.3.0]
1.2.0 (July 16, 2010) 1.2.0 (July 16, 2010)
@@ -206,11 +280,15 @@
* Adding joins clause to accessible_by when conditions are across associations * Adding joins clause to accessible_by when conditions are across associations
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.1.1...1.2.0]
1.1.1 (April 17, 2010) 1.1.1 (April 17, 2010)
* Fixing behavior in Rails 3 by properly initializing ResourceAuthorization * Fixing behavior in Rails 3 by properly initializing ResourceAuthorization
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.1...1.1.1]
1.1.0 (April 17, 2010) 1.1.0 (April 17, 2010)
@@ -234,6 +312,8 @@
* Support additional arguments to can? which get passed to the block - see issue #48 * Support additional arguments to can? which get passed to the block - see issue #48
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.0.2...1.1]
1.0.2 (Dec 30, 2009) 1.0.2 (Dec 30, 2009)
@@ -243,6 +323,8 @@
* Adding custom message argument to unauthorized! method (thanks tjwallace) - see issue #18 * Adding custom message argument to unauthorized! method (thanks tjwallace) - see issue #18
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.0.1...1.0.2]
1.0.1 (Dec 14, 2009) 1.0.1 (Dec 14, 2009)
@@ -250,6 +332,8 @@
* Don't fetch parent of nested resource if *_id parameter is missing so it works with shallow nested routes - see issue #14 * Don't fetch parent of nested resource if *_id parameter is missing so it works with shallow nested routes - see issue #14
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.0.0...1.0.1]
1.0.0 (Dec 13, 2009) 1.0.0 (Dec 13, 2009)
@@ -265,6 +349,8 @@
* BACKWARDS INCOMPATIBLE: turning load and authorize resource methods into class methods which set up the before filter so they can accept additional arguments. * BACKWARDS INCOMPATIBLE: turning load and authorize resource methods into class methods which set up the before filter so they can accept additional arguments.
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/0.2.1...1.0.0]
0.2.1 (Nov 26, 2009) 0.2.1 (Nov 26, 2009)
@@ -274,6 +360,8 @@
* support custom objects (usually symbols) in can definition - see issue #8 * support custom objects (usually symbols) in can definition - see issue #8
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/0.2.0...0.2.1]
0.2.0 (Nov 17, 2009) 0.2.0 (Nov 17, 2009)
@@ -285,6 +373,8 @@
* BACKWARDS INCOMPATIBLE: use Ability#initialize instead of 'prepare' to set up abilities - see issue #4 * BACKWARDS INCOMPATIBLE: use Ability#initialize instead of 'prepare' to set up abilities - see issue #4
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/0.1.0...0.2.0]
0.1.0 (Nov 16, 2009) 0.1.0 (Nov 16, 2009)

View File

@@ -3,8 +3,8 @@ source "http://rubygems.org"
case ENV["MODEL_ADAPTER"] case ENV["MODEL_ADAPTER"]
when nil, "active_record" when nil, "active_record"
gem "sqlite3" gem "sqlite3"
gem "activerecord", :require => "active_record" gem "activerecord", '~> 3.0.9', :require => "active_record"
gem "with_model" gem "with_model", "~> 0.2.5"
gem "meta_where" gem "meta_where"
when "data_mapper" when "data_mapper"
gem "dm-core", "~> 1.0.2" gem "dm-core", "~> 1.0.2"

View File

@@ -1,4 +1,4 @@
= CanCan = CanCan {<img src="https://secure.travis-ci.org/ryanb/cancan.png" />}[http://travis-ci.org/ryanb/cancan]
Wiki[https://github.com/ryanb/cancan/wiki] | RDocs[http://rdoc.info/projects/ryanb/cancan] | Screencast[http://railscasts.com/episodes/192-authorization-with-cancan] Wiki[https://github.com/ryanb/cancan/wiki] | RDocs[http://rdoc.info/projects/ryanb/cancan] | Screencast[http://railscasts.com/episodes/192-authorization-with-cancan]
@@ -31,6 +31,15 @@ User permissions are defined in an +Ability+ class. CanCan 1.5 includes a Rails
rails g cancan:ability rails g cancan:ability
In Rails 2.3, just add a new class in `app/models/ability.rb` with the folowing contents:
class Ability
include CanCan::Ability
def initialize(user)
end
end
See {Defining Abilities}[https://github.com/ryanb/cancan/wiki/defining-abilities] for details. See {Defining Abilities}[https://github.com/ryanb/cancan/wiki/defining-abilities] for details.

View File

@@ -1,6 +1,6 @@
Gem::Specification.new do |s| Gem::Specification.new do |s|
s.name = "cancan" s.name = "cancan"
s.version = "1.6.5" s.version = "1.6.8"
s.author = "Ryan Bates" s.author = "Ryan Bates"
s.email = "ryan@railscasts.com" s.email = "ryan@railscasts.com"
s.homepage = "http://github.com/ryanb/cancan" s.homepage = "http://github.com/ryanb/cancan"
@@ -10,8 +10,8 @@ Gem::Specification.new do |s|
s.files = Dir["{lib,spec}/**/*", "[A-Z]*", "init.rb"] - ["Gemfile.lock"] s.files = Dir["{lib,spec}/**/*", "[A-Z]*", "init.rb"] - ["Gemfile.lock"]
s.require_path = "lib" s.require_path = "lib"
s.add_development_dependency 'rspec', '~> 2.1.0' s.add_development_dependency 'rspec', '~> 2.6.0'
s.add_development_dependency 'rails', '~> 3.0.0' s.add_development_dependency 'rails', '~> 3.0.9'
s.add_development_dependency 'rr', '~> 0.10.11' # 1.0.0 has respond_to? issues: http://github.com/btakita/rr/issues/issue/43 s.add_development_dependency 'rr', '~> 0.10.11' # 1.0.0 has respond_to? issues: http://github.com/btakita/rr/issues/issue/43
s.add_development_dependency 'supermodel', '~> 0.1.4' s.add_development_dependency 'supermodel', '~> 0.1.4'

View File

@@ -228,6 +228,13 @@ module CanCan
relevant_rules(action, subject).any?(&:only_raw_sql?) relevant_rules(action, subject).any?(&:only_raw_sql?)
end end
def merge(ability)
ability.send(:rules).each do |rule|
rules << rule.dup
end
self
end
private private
def unauthorized_message_keys(action, subject) def unauthorized_message_keys(action, subject)

View File

@@ -94,7 +94,7 @@ module CanCan
# [:+find_by+] # [:+find_by+]
# Find using a different attribute other than id. For example. # Find using a different attribute other than id. For example.
# #
# load_resource :find_by => :permalink # will use find_by_permlink!(params[:id]) # load_resource :find_by => :permalink # will use find_by_permalink!(params[:id])
# #
# [:+collection+] # [:+collection+]
# Specify which actions are resource collection actions in addition to :+index+. This # Specify which actions are resource collection actions in addition to :+index+. This
@@ -151,6 +151,9 @@ module CanCan
# [:+except+] # [:+except+]
# Does not apply before filter to given actions. # Does not apply before filter to given actions.
# #
# [:+singleton+]
# Pass +true+ if this is a singleton resource through a +has_one+ association.
#
# [:+parent+] # [:+parent+]
# True or false depending on if the resource is considered a parent resource. This defaults to +true+ if a resource # True or false depending on if the resource is considered a parent resource. This defaults to +true+ if a resource
# name is given which does not match the controller. # name is given which does not match the controller.
@@ -186,7 +189,7 @@ module CanCan
skip_authorize_resource(*args) skip_authorize_resource(*args)
end end
# Skip both the loading behavior of CanCan. This is useful when using +load_and_authorize_resource+ but want to # Skip the loading behavior of CanCan. This is useful when using +load_and_authorize_resource+ but want to
# only do authorization on certain actions. You can pass :only and :except options to specify which actions to # only do authorization on certain actions. You can pass :only and :except options to specify which actions to
# skip the effects on. It will apply to all actions by default. # skip the effects on. It will apply to all actions by default.
# #
@@ -202,7 +205,7 @@ module CanCan
cancan_skipper[:load][name] = options cancan_skipper[:load][name] = options
end end
# Skip both the authorization behavior of CanCan. This is useful when using +load_and_authorize_resource+ but want to # Skip the authorization behavior of CanCan. This is useful when using +load_and_authorize_resource+ but want to
# only do loading on certain actions. You can pass :only and :except options to specify which actions to # only do loading on certain actions. You can pass :only and :except options to specify which actions to
# skip the effects on. It will apply to all actions by default. # skip the effects on. It will apply to all actions by default.
# #
@@ -247,9 +250,9 @@ module CanCan
# #
def check_authorization(options = {}) def check_authorization(options = {})
self.after_filter(options.slice(:only, :except)) do |controller| self.after_filter(options.slice(:only, :except)) do |controller|
return if controller.instance_variable_defined?(:@_authorized) next if controller.instance_variable_defined?(:@_authorized)
return if options[:if] && !controller.send(options[:if]) next if options[:if] && !controller.send(options[:if])
return if options[:unless] && controller.send(options[:unless]) next if options[:unless] && controller.send(options[:unless])
raise AuthorizationNotPerformed, "This action failed the check_authorization because it does not authorize_resource. Add skip_authorization_check to bypass this check." raise AuthorizationNotPerformed, "This action failed the check_authorization because it does not authorize_resource. Add skip_authorization_check to bypass this check."
end end
end end
@@ -382,7 +385,7 @@ module CanCan
end end
end end
if defined? ActionController if defined? ActionController::Base
ActionController::Base.class_eval do ActionController::Base.class_eval do
include CanCan::ControllerAdditions include CanCan::ControllerAdditions
end end

View File

@@ -6,8 +6,8 @@ module CanCan
options = args.extract_options! options = args.extract_options!
resource_name = args.first resource_name = args.first
before_filter_method = options.delete(:prepend) ? :prepend_before_filter : :before_filter before_filter_method = options.delete(:prepend) ? :prepend_before_filter : :before_filter
controller_class.send(before_filter_method, options.slice(:only, :except)) do |controller| controller_class.send(before_filter_method, options.slice(:only, :except, :if, :unless)) do |controller|
controller.class.cancan_resource_class.new(controller, resource_name, options.except(:only, :except)).send(method) controller.class.cancan_resource_class.new(controller, resource_name, options.except(:only, :except, :if, :unless)).send(method)
end end
end end
@@ -82,7 +82,11 @@ module CanCan
end end
def build_resource def build_resource
resource = resource_base.new(@params[name] || {}) resource = resource_base.new(resource_params || {})
assign_attributes(resource)
end
def assign_attributes(resource)
resource.send("#{parent_name}=", parent_resource) if @options[:singleton] && parent_resource resource.send("#{parent_name}=", parent_resource) if @options[:singleton] && parent_resource
initial_attributes.each do |attr_name, value| initial_attributes.each do |attr_name, value|
resource.send("#{attr_name}=", value) resource.send("#{attr_name}=", value)
@@ -92,7 +96,7 @@ module CanCan
def initial_attributes def initial_attributes
current_ability.attributes_for(@params[:action].to_sym, resource_class).delete_if do |key, value| current_ability.attributes_for(@params[:action].to_sym, resource_class).delete_if do |key, value|
@params[name] && @params[name].include?(key) resource_params && resource_params.include?(key)
end end
end end
@@ -100,20 +104,36 @@ module CanCan
if @options[:singleton] && parent_resource.respond_to?(name) if @options[:singleton] && parent_resource.respond_to?(name)
parent_resource.send(name) parent_resource.send(name)
else else
@options[:find_by] ? resource_base.send("find_by_#{@options[:find_by]}!", id_param) : resource_base.find(id_param) if @options[:find_by]
if resource_base.respond_to? "find_by_#{@options[:find_by]}!"
resource_base.send("find_by_#{@options[:find_by]}!", id_param)
else
resource_base.send(@options[:find_by], id_param)
end
else
adapter.find(resource_base, id_param)
end
end end
end end
def adapter
ModelAdapters::AbstractAdapter.adapter_class(resource_class)
end
def authorization_action def authorization_action
parent? ? :show : @params[:action].to_sym parent? ? :show : @params[:action].to_sym
end end
def id_param def id_param
@params[parent? ? :"#{name}_id" : :id] if @options[:id_param]
@params[@options[:id_param]]
else
@params[parent? ? :"#{name}_id" : :id]
end
end end
def member_action? def member_action?
new_actions.include?(@params[:action].to_sym) || @options[:singleton] || (@params[:id] && !collection_actions.include?(@params[:action].to_sym)) new_actions.include?(@params[:action].to_sym) || @options[:singleton] || ( (@params[:id] || @params[@options[:id_param]]) && !collection_actions.include?(@params[:action].to_sym))
end end
# Returns the class used for this resource. This can be overriden by the :class option. # Returns the class used for this resource. This can be overriden by the :class option.
@@ -122,7 +142,7 @@ module CanCan
def resource_class def resource_class
case @options[:class] case @options[:class]
when false then name.to_sym when false then name.to_sym
when nil then name.to_s.camelize.constantize when nil then namespaced_name.to_s.camelize.constantize
when String then @options[:class].constantize when String then @options[:class].constantize
else @options[:class] else @options[:class]
end end
@@ -191,6 +211,24 @@ module CanCan
@name || name_from_controller @name || name_from_controller
end end
def resource_params
if @options[:class]
@params[@options[:class].to_s.underscore.gsub('/', '_')]
else
@params[namespaced_name.to_s.underscore.gsub("/", "_")]
end
end
def namespace
@params[:controller].split("::")[0..-2]
end
def namespaced_name
[namespace, name.camelize].join('::').singularize.camelize.constantize
rescue NameError
name
end
def name_from_controller def name_from_controller
@params[:controller].sub("Controller", "").underscore.split('/').last.singularize @params[:controller].sub("Controller", "").underscore.split('/').last.singularize
end end

View File

@@ -40,7 +40,7 @@ module CanCan
@message = message @message = message
@action = action @action = action
@subject = subject @subject = subject
@default_message = "You are not authorized to access this page." @default_message = I18n.t(:"unauthorized.default", :default => "You are not authorized to access this page.")
end end
def to_s def to_s

View File

@@ -6,7 +6,8 @@ module CanCan
@controller.send :association_chain @controller.send :association_chain
@controller.instance_variable_get("@#{instance_name}") @controller.instance_variable_get("@#{instance_name}")
elsif new_actions.include? @params[:action].to_sym elsif new_actions.include? @params[:action].to_sym
@controller.send :build_resource resource = @controller.send :build_resource
assign_attributes(resource)
else else
@controller.send :resource @controller.send :resource
end end

View File

@@ -1,5 +1,5 @@
RSpec = Spec unless defined? RSpec # for RSpec 1 compatability rspec_module = defined?(RSpec::Core) ? 'RSpec' : 'Spec' # for RSpec 1 compatability
RSpec::Matchers.define :be_able_to do |*args| Kernel.const_get(rspec_module)::Matchers.define :be_able_to do |*args|
match do |ability| match do |ability|
ability.can?(*args) ability.can?(*args)
end end

View File

@@ -15,6 +15,11 @@ module CanCan
false # override in subclass false # override in subclass
end end
# Override if you need custom find behavior
def self.find(model_class, id)
model_class.find(id)
end
# Used to determine if this model adapter will override the matching behavior for a hash of conditions. # Used to determine if this model adapter will override the matching behavior for a hash of conditions.
# If this returns true then matches_conditions_hash? will be called. See Rule#matches_conditions_hash # If this returns true then matches_conditions_hash? will be called. See Rule#matches_conditions_hash
def self.override_conditions_hash_matching?(subject, conditions) def self.override_conditions_hash_matching?(subject, conditions)

View File

@@ -89,7 +89,12 @@ module CanCan
if override_scope if override_scope
@model_class.scoped.merge(override_scope) @model_class.scoped.merge(override_scope)
elsif @model_class.respond_to?(:where) && @model_class.respond_to?(:joins) elsif @model_class.respond_to?(:where) && @model_class.respond_to?(:joins)
@model_class.where(conditions).joins(joins) mergeable_conditions = @rules.select {|rule| rule.unmergeable? }.blank?
if mergeable_conditions
@model_class.where(conditions).joins(joins)
else
@model_class.where(*(@rules.map(&:conditions))).joins(joins)
end
else else
@model_class.scoped(:conditions => conditions, :joins => joins) @model_class.scoped(:conditions => conditions, :joins => joins)
end end

View File

@@ -5,6 +5,10 @@ module CanCan
model_class <= DataMapper::Resource model_class <= DataMapper::Resource
end end
def self.find(model_class, id)
model_class.get(id)
end
def self.override_conditions_hash_matching?(subject, conditions) def self.override_conditions_hash_matching?(subject, conditions)
conditions.any? { |k,v| !k.kind_of?(Symbol) } conditions.any? { |k,v| !k.kind_of?(Symbol) }
end end
@@ -27,6 +31,4 @@ module CanCan
end # module ModelAdapters end # module ModelAdapters
end # module CanCan end # module CanCan
DataMapper::Model.class_eval do DataMapper::Model.append_extensions(CanCan::ModelAdditions::ClassMethods)
include CanCan::ModelAdditions::ClassMethods
end

View File

@@ -30,8 +30,9 @@ module CanCan
else else
# we only need to process can rules if # we only need to process can rules if
# there are no rules with empty conditions # there are no rules with empty conditions
rules = @rules.reject { |rule| rule.conditions.empty? } rules = @rules.reject { |rule| rule.conditions.empty? && rule.base_behavior }
process_can_rules = @rules.count == rules.count process_can_rules = @rules.count == rules.count
rules.inject(@model_class.all) do |records, rule| rules.inject(@model_class.all) do |records, rule|
if process_can_rules && rule.base_behavior if process_can_rules && rule.base_behavior
records.or rule.conditions records.or rule.conditions

View File

@@ -54,6 +54,10 @@ module CanCan
@conditions == {} || @conditions.nil? @conditions == {} || @conditions.nil?
end end
def unmergeable?
@conditions.respond_to?(:keys) && (! @conditions.keys.first.kind_of? Symbol)
end
def associations_hash(conditions = @conditions) def associations_hash(conditions = @conditions)
hash = {} hash = {}
conditions.map do |name, value| conditions.map do |name, value|
@@ -111,7 +115,7 @@ module CanCan
else else
!attribute.nil? && matches_conditions_hash?(attribute, value) !attribute.nil? && matches_conditions_hash?(attribute, value)
end end
elsif value.kind_of?(Array) || value.kind_of?(Range) elsif value.kind_of?(Enumerable)
value.include? attribute value.include? attribute
else else
attribute == value attribute == value
@@ -123,7 +127,7 @@ module CanCan
end end
def nested_subject_matches_conditions?(subject_hash) def nested_subject_matches_conditions?(subject_hash)
parent, child = subject_hash.shift parent, child = subject_hash.first
matches_conditions_hash?(parent, @conditions[parent.class.name.downcase.to_sym] || {}) matches_conditions_hash?(parent, @conditions[parent.class.name.downcase.to_sym] || {})
end end
@@ -136,7 +140,7 @@ module CanCan
end end
def model_adapter(subject) def model_adapter(subject)
ModelAdapters::AbstractAdapter.adapter_class(subject_class?(subject) ? subject : subject.class) CanCan::ModelAdapters::AbstractAdapter.adapter_class(subject_class?(subject) ? subject : subject.class)
end end
end end
end end

View File

@@ -249,7 +249,15 @@ describe CanCan::Ability do
@ability.can?(:read, 1..5).should be_true @ability.can?(:read, 1..5).should be_true
@ability.can?(:read, 4..6).should be_false @ability.can?(:read, 4..6).should be_false
end end
it "should accept a set as a condition value" do
mock(object_with_foo_2 = Object.new).foo { 2 }
mock(object_with_foo_3 = Object.new).foo { 3 }
@ability.can :read, Object, :foo => [1, 2, 5].to_set
@ability.can?(:read, object_with_foo_2).should be_true
@ability.can?(:read, object_with_foo_3).should be_false
end
it "should not match subjects return nil for methods that must match nested a nested conditions hash" do it "should not match subjects return nil for methods that must match nested a nested conditions hash" do
mock(object_with_foo = Object.new).foo { :bar } mock(object_with_foo = Object.new).foo { :bar }
@ability.can :read, Array, :first => { :foo => :bar } @ability.can :read, Array, :first => { :foo => :bar }
@@ -297,7 +305,15 @@ describe CanCan::Ability do
@ability.can?(:read, "foobar" => Range).should be_false @ability.can?(:read, "foobar" => Range).should be_false
@ability.can?(:read, 123 => Range).should be_true @ability.can?(:read, 123 => Range).should be_true
end end
it "passing a hash of subjects with multiple definitions should check permissions correctly" do
@ability.can :read, Range, :string => {:length => 4}
@ability.can [:create, :read], Range, :string => {:upcase => 'FOO'}
@ability.can?(:read, "foo" => Range).should be_true
@ability.can?(:read, "foobar" => Range).should be_false
@ability.can?(:read, 1234 => Range).should be_true
end
it "should allow to check ability on Hash-like object" do it "should allow to check ability on Hash-like object" do
class Container < Hash; end class Container < Hash; end
@ability.can :read, Container @ability.can :read, Container
@@ -416,4 +432,17 @@ describe CanCan::Ability do
@ability.unauthorized_message(:edit, 1..3).should == "edit range" @ability.unauthorized_message(:edit, 1..3).should == "edit range"
end end
end end
describe "#merge" do
it "should add the rules from the given ability" do
@ability.can :use, :tools
another_ability = Object.new
another_ability.extend(CanCan::Ability)
another_ability.can :use, :search
@ability.merge(another_ability)
@ability.can?(:use, :search).should be_true
@ability.send(:rules).size.should == 2
end
end
end end

View File

@@ -49,14 +49,14 @@ describe CanCan::ControllerAdditions do
it "authorize_resource should setup a before filter which passes call to ControllerResource" do it "authorize_resource should setup a before filter which passes call to ControllerResource" do
stub(CanCan::ControllerResource).new(@controller, nil, :foo => :bar).mock!.authorize_resource stub(CanCan::ControllerResource).new(@controller, nil, :foo => :bar).mock!.authorize_resource
mock(@controller_class).before_filter(:except => :show) { |options, block| block.call(@controller) } mock(@controller_class).before_filter(:except => :show, :if => true) { |options, block| block.call(@controller) }
@controller_class.authorize_resource :foo => :bar, :except => :show @controller_class.authorize_resource :foo => :bar, :except => :show, :if => true
end end
it "load_resource should setup a before filter which passes call to ControllerResource" do it "load_resource should setup a before filter which passes call to ControllerResource" do
stub(CanCan::ControllerResource).new(@controller, nil, :foo => :bar).mock!.load_resource stub(CanCan::ControllerResource).new(@controller, nil, :foo => :bar).mock!.load_resource
mock(@controller_class).before_filter(:only => [:show, :index]) { |options, block| block.call(@controller) } mock(@controller_class).before_filter(:only => [:show, :index], :unless => false) { |options, block| block.call(@controller) }
@controller_class.load_resource :foo => :bar, :only => [:show, :index] @controller_class.load_resource :foo => :bar, :only => [:show, :index], :unless => false
end end
it "skip_authorization_check should set up a before filter which sets @_authorized to true" do it "skip_authorization_check should set up a before filter which sets @_authorized to true" do

View File

@@ -35,6 +35,30 @@ describe CanCan::ControllerResource do
@controller.instance_variable_get(:@project).should == project @controller.instance_variable_get(:@project).should == project
end end
it "should attempt to load a resource with the same namespace as the controller when using :: for namespace" do
module MyEngine
class Project < ::Project; end
end
project = MyEngine::Project.create!
@params.merge!(:controller => "MyEngine::ProjectsController", :action => "show", :id => project.id)
resource = CanCan::ControllerResource.new(@controller)
resource.load_resource
@controller.instance_variable_get(:@project).should == project
end
# Rails includes namespace in params, see issue #349
it "should create through the namespaced params" do
module MyEngine
class Project < ::Project; end
end
@params.merge!(:controller => "MyEngine::ProjectsController", :action => "create", :my_engine_project => {:name => "foobar"})
resource = CanCan::ControllerResource.new(@controller)
resource.load_resource
@controller.instance_variable_get(:@project).name.should == "foobar"
end
it "should properly load resource for namespaced controller when using '::' for namespace" do it "should properly load resource for namespaced controller when using '::' for namespace" do
project = Project.create! project = Project.create!
@params.merge!(:controller => "Admin::ProjectsController", :action => "show", :id => project.id) @params.merge!(:controller => "Admin::ProjectsController", :action => "show", :id => project.id)
@@ -50,6 +74,14 @@ describe CanCan::ControllerResource do
@controller.instance_variable_get(:@project).name.should == "foobar" @controller.instance_variable_get(:@project).name.should == "foobar"
end end
it "should build a new resource for namespaced model with hash if params[:id] is not specified" do
project = Sub::Project.create!
@params.merge!(:action => "create", 'sub_project' => {:name => "foobar"})
resource = CanCan::ControllerResource.new(@controller, :class => ::Sub::Project)
resource.load_resource
@controller.instance_variable_get(:@project).name.should == "foobar"
end
it "should build a new resource with attributes from current ability" do it "should build a new resource with attributes from current ability" do
@params.merge!(:action => "new") @params.merge!(:action => "new")
@ability.can(:create, Project, :name => "from conditions") @ability.can(:create, Project, :name => "from conditions")
@@ -183,10 +215,18 @@ describe CanCan::ControllerResource do
resource.should_not be_parent resource.should_not be_parent
end end
it "should have the specified resource_class if 'name' is passed to load_resource" do
class Section
end
resource = CanCan::ControllerResource.new(@controller, :section)
resource.send(:resource_class).should == Section
end
it "should load parent resource through proper id parameter" do it "should load parent resource through proper id parameter" do
project = Project.create! project = Project.create!
@params.merge!(:action => "index", :project_id => project.id) @params.merge!(:controller => "categories", :action => "index", :project_id => project.id)
resource = CanCan::ControllerResource.new(@controller, :project, :parent => true) resource = CanCan::ControllerResource.new(@controller, :project)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@project).should == project @controller.instance_variable_get(:@project).should == project
end end
@@ -312,6 +352,14 @@ describe CanCan::ControllerResource do
@controller.instance_variable_get(:@project).should == project @controller.instance_variable_get(:@project).should == project
end end
it "should load the model using a custom namespaced class" do
project = Sub::Project.create!
@params.merge!(:action => "show", :id => project.id)
resource = CanCan::ControllerResource.new(@controller, :class => ::Sub::Project)
resource.load_resource
@controller.instance_variable_get(:@project).should == project
end
it "should authorize based on resource name if class is false" do it "should authorize based on resource name if class is false" do
@params.merge!(:action => "show", :id => 123) @params.merge!(:action => "show", :id => 123)
stub(@controller).authorize!(:show, :project) { raise CanCan::AccessDenied } stub(@controller).authorize!(:show, :project) { raise CanCan::AccessDenied }
@@ -328,6 +376,14 @@ describe CanCan::ControllerResource do
@controller.instance_variable_get(:@custom_project).should == project @controller.instance_variable_get(:@custom_project).should == project
end end
it "should load resource using custom ID param" do
project = Project.create!
@params.merge!(:action => "show", :the_project => project.id)
resource = CanCan::ControllerResource.new(@controller, :id_param => :the_project)
resource.load_resource
@controller.instance_variable_get(:@project).should == project
end
it "should load resource using custom find_by attribute" do it "should load resource using custom find_by attribute" do
project = Project.create!(:name => "foo") project = Project.create!(:name => "foo")
@params.merge!(:action => "show", :id => "foo") @params.merge!(:action => "show", :id => "foo")
@@ -336,6 +392,14 @@ describe CanCan::ControllerResource do
@controller.instance_variable_get(:@project).should == project @controller.instance_variable_get(:@project).should == project
end end
it "should allow full find method to be passed into find_by option" do
project = Project.create!(:name => "foo")
@params.merge!(:action => "show", :id => "foo")
resource = CanCan::ControllerResource.new(@controller, :find_by => :find_by_name)
resource.load_resource
@controller.instance_variable_get(:@project).should == project
end
it "should raise ImplementationRemoved when adding :name option" do it "should raise ImplementationRemoved when adding :name option" do
lambda { lambda {
CanCan::ControllerResource.new(@controller, :name => :foo) CanCan::ControllerResource.new(@controller, :name => :foo)

View File

@@ -32,4 +32,27 @@ describe CanCan::AccessDenied do
@exception.message.should == "Access denied!" @exception.message.should == "Access denied!"
end end
end end
describe "i18n in the default message" do
after(:each) do
I18n.backend = nil
end
it "uses i18n for the default message" do
I18n.backend.store_translations :en, :unauthorized => {:default => "This is a different message"}
@exception = CanCan::AccessDenied.new
@exception.message.should == "This is a different message"
end
it "defaults to a nice message" do
@exception = CanCan::AccessDenied.new
@exception.message.should == "You are not authorized to access this page."
end
it "does not use translation if a message is given" do
@exception = CanCan::AccessDenied.new("Hey! You're not welcome here")
@exception.message.should == "Hey! You're not welcome here"
@exception.message.should_not == "You are not authorized to access this page."
end
end
end end

View File

@@ -39,4 +39,22 @@ describe CanCan::InheritedResource do
CanCan::InheritedResource.new(@controller).load_resource CanCan::InheritedResource.new(@controller).load_resource
@controller.instance_variable_get(:@projects).should == :projects @controller.instance_variable_get(:@projects).should == :projects
end end
it "should build a new resource with attributes from current ability" do
@params[:action] = "new"
@ability.can(:create, Project, :name => "from conditions")
stub(@controller).build_resource { Struct.new(:name).new }
resource = CanCan::InheritedResource.new(@controller)
resource.load_resource
@controller.instance_variable_get(:@project).name.should == "from conditions"
end
it "should override initial attributes with params" do
@params.merge!(:action => "new", :project => {:name => "from params"})
@ability.can(:create, Project, :name => "from conditions")
stub(@controller).build_resource { Struct.new(:name).new }
resource = CanCan::ControllerResource.new(@controller)
resource.load_resource
@controller.instance_variable_get(:@project).name.should == "from params"
end
end end

View File

@@ -1,10 +1,6 @@
if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record" if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
require "spec_helper" require "spec_helper"
RSpec.configure do |config|
config.extend WithModel
end
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:") ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
describe CanCan::ModelAdapters::ActiveRecordAdapter do describe CanCan::ModelAdapters::ActiveRecordAdapter do
@@ -56,6 +52,11 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article).should == CanCan::ModelAdapters::ActiveRecordAdapter CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article).should == CanCan::ModelAdapters::ActiveRecordAdapter
end end
it "should find record" do
article = Article.create!
CanCan::ModelAdapters::ActiveRecordAdapter.find(Article, article.id).should == article
end
it "should not fetch any records when no abilities are defined" do it "should not fetch any records when no abilities are defined" do
Article.create! Article.create!
Article.accessible_by(@ability).should be_empty Article.accessible_by(@ability).should be_empty
@@ -132,7 +133,7 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
article1 = Article.create!(:secret => true, :category => category1) article1 = Article.create!(:secret => true, :category => category1)
article2 = Article.create!(:secret => true, :category => category2) article2 = Article.create!(:secret => true, :category => category2)
category1.articles.accessible_by(@ability).should == [article1] category1.articles.accessible_by(@ability).should == [article1]
end end
it "should raise an exception when trying to merge scope with other conditions" do it "should raise an exception when trying to merge scope with other conditions" do
@ability.can :read, Article, :published => true @ability.can :read, Article, :published => true
@@ -235,6 +236,16 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
@ability.should_not be_able_to(:read, article2) @ability.should_not be_able_to(:read, article2)
end end
it "should merge MetaWhere and non-MetaWhere conditions" do
@ability.can :read, Article, :priority.lt => 2
@ability.can :read, Article, :priority => 1
article1 = Article.create!(:priority => 1)
article2 = Article.create!(:priority => 3)
Article.accessible_by(@ability).should == [article1]
@ability.should be_able_to(:read, article1)
@ability.should_not be_able_to(:read, article2)
end
it "should match any MetaWhere condition" do it "should match any MetaWhere condition" do
adapter = CanCan::ModelAdapters::ActiveRecordAdapter adapter = CanCan::ModelAdapters::ActiveRecordAdapter
article1 = Article.new(:priority => 1, :name => "Hello World") article1 = Article.new(:priority => 1, :name => "Hello World")

View File

@@ -36,6 +36,11 @@ if ENV["MODEL_ADAPTER"] == "data_mapper"
CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article).should == CanCan::ModelAdapters::DataMapperAdapter CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article).should == CanCan::ModelAdapters::DataMapperAdapter
end end
it "should find record" do
article = Article.create
CanCan::ModelAdapters::DataMapperAdapter.find(Article, article.id).should == article
end
it "should not fetch any records when no abilities are defined" do it "should not fetch any records when no abilities are defined" do
Article.create Article.create
Article.accessible_by(@ability).should be_empty Article.accessible_by(@ability).should be_empty

View File

@@ -36,6 +36,11 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
CanCan::ModelAdapters::AbstractAdapter.adapter_class(MongoidProject).should == CanCan::ModelAdapters::MongoidAdapter CanCan::ModelAdapters::AbstractAdapter.adapter_class(MongoidProject).should == CanCan::ModelAdapters::MongoidAdapter
end end
it "should find record" do
project = MongoidProject.create
CanCan::ModelAdapters::MongoidAdapter.find(MongoidProject, project.id).should == project
end
it "should compare properties on mongoid documents with the conditions hash" do it "should compare properties on mongoid documents with the conditions hash" do
model = MongoidProject.new model = MongoidProject.new
@ability.can :read, MongoidProject, :id => model.id @ability.can :read, MongoidProject, :id => model.id
@@ -68,6 +73,17 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
MongoidProject.accessible_by(@ability, :read).entries.should == [sir] MongoidProject.accessible_by(@ability, :read).entries.should == [sir]
end end
it "should return the correct records when a mix of can and cannot rules in defined ability" do
@ability.can :manage, MongoidProject, :title => 'Sir'
@ability.cannot :destroy, MongoidProject
sir = MongoidProject.create(:title => 'Sir')
lord = MongoidProject.create(:title => 'Lord')
dude = MongoidProject.create(:title => 'Dude')
MongoidProject.accessible_by(@ability, :destroy).entries.should == [sir]
end
it "should be able to mix empty conditions and hashes" do it "should be able to mix empty conditions and hashes" do
@ability.can :read, MongoidProject @ability.can :read, MongoidProject
@ability.can :read, MongoidProject, :title => 'Sir' @ability.can :read, MongoidProject, :title => 'Sir'
@@ -180,7 +196,7 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
@ability.can :read, MongoidProject, :foo => {:bar => 1} @ability.can :read, MongoidProject, :foo => {:bar => 1}
MongoidProject.accessible_by(@ability, :read).entries.first.should == obj MongoidProject.accessible_by(@ability, :read).entries.first.should == obj
end end
it "should exclude from the result if set to cannot" do it "should exclude from the result if set to cannot" do
obj = MongoidProject.create(:bar => 1) obj = MongoidProject.create(:bar => 1)
obj2 = MongoidProject.create(:bar => 2) obj2 = MongoidProject.create(:bar => 2)
@@ -197,7 +213,7 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
@ability.can :read, MongoidProject, :bar => 2 @ability.can :read, MongoidProject, :bar => 2
MongoidProject.accessible_by(@ability, :read).entries.should =~ [obj, obj2] MongoidProject.accessible_by(@ability, :read).entries.should =~ [obj, obj2]
end end
it "should not allow to fetch records when ability with just block present" do it "should not allow to fetch records when ability with just block present" do
@ability.can :read, MongoidProject do @ability.can :read, MongoidProject do
false false

View File

@@ -1,4 +1,5 @@
require "spec_helper" require "spec_helper"
require "ostruct" # for OpenStruct below
# Most of Rule functionality is tested in Ability specs # Most of Rule functionality is tested in Ability specs
describe CanCan::Rule do describe CanCan::Rule do
@@ -36,4 +37,11 @@ describe CanCan::Rule do
rule = CanCan::Rule.new(true, :read, Integer, nil, nil) rule = CanCan::Rule.new(true, :read, Integer, nil, nil)
rule.associations_hash.should == {} rule.associations_hash.should == {}
end end
it "should not be mergeable if conditions are not simple hashes" do
meta_where = OpenStruct.new(:name => 'metawhere', :column => 'test')
@conditions[meta_where] = :bar
@rule.should be_unmergeable
end
end end

View File

@@ -9,11 +9,15 @@ require 'matchers'
require 'cancan/matchers' require 'cancan/matchers'
RSpec.configure do |config| RSpec.configure do |config|
config.treat_symbols_as_metadata_keys_with_true_values = true
config.filter_run :focus => true
config.run_all_when_everything_filtered = true
config.mock_with :rr config.mock_with :rr
config.before(:each) do config.before(:each) do
Project.delete_all Project.delete_all
Category.delete_all Category.delete_all
end end
config.extend WithModel if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
end end
class Ability class Ability
@@ -27,7 +31,30 @@ class Category < SuperModel::Base
has_many :projects has_many :projects
end end
module Sub
class Project < SuperModel::Base
belongs_to :category
attr_accessor :category # why doesn't SuperModel do this automatically?
def self.respond_to?(method, include_private = false)
if method.to_s == "find_by_name!" # hack to simulate ActiveRecord
true
else
super
end
end
end
end
class Project < SuperModel::Base class Project < SuperModel::Base
belongs_to :category belongs_to :category
attr_accessor :category # why doesn't SuperModel do this automatically? attr_accessor :category # why doesn't SuperModel do this automatically?
def self.respond_to?(method, include_private = false)
if method.to_s == "find_by_name!" # hack to simulate ActiveRecord
true
else
super
end
end
end end