Allow mixing of protected and accessible properties.

Any unspecified properties are now assumed to be protected by default
This commit is contained in:
Will Leinweber 2010-08-11 17:41:32 -05:00
parent bf22222fd9
commit aac6b80d26
4 changed files with 67 additions and 55 deletions

3
.gitignore vendored
View file

@ -2,3 +2,6 @@
html/*
pkg
*.swp
Gemfile*
.rvmrc
.bundle

View file

@ -4,12 +4,13 @@
* Minor enhancements
* Raise error on adding objects to "collection_of" without an id
* Allow mixing of protected and accessible properties. Any unspecified properties are now assumed to be protected by default
== CouchRest Model 1.0.0.beta7
* Major enhancements
* Renamed ExtendedDocument to CouchRest::Model
* Added initial support for simple belongs_to associations
* Added initial support for simple belongs_to associations
* Added support for basic collection_of association (unique to document databases!)
* Moved Validation to ActiveModel
* Moved Callbacks to ActiveModel
@ -74,7 +75,7 @@
* Adds support for continuous replication (sauy7)
* Automatic Type Casting (Alexander Uvarov, Sam Lown, Tim Heighes, Will Leinweber)
* Added a search method to CouchRest:Database to search the documents in a given database. (Dave Farkas, Arnaud Berthomier, John Wood)
* Minor enhancements
* Provide a description of the timeout error (John Wood)
@ -103,9 +104,9 @@
* Adds attribute protection to properties. (Will Leinweber)
* Improved CouchRest::Database#save_doc, added "batch" mode to significantly speed up saves at cost of lower durability gurantees. (Igal Koshevoy)
* Added CouchRest::Database#bulk_save_doc and #batch_save_doc as human-friendlier wrappers around #save_doc. (Igal Koshevoy)
* Minor enhancements
* Minor enhancements
* Fix content_type handling for attachments
* Fixed a bug in the pagination code that caused it to paginate over records outside of the scope of the view parameters.(John Wood)
* Removed amount_pages calculation for the pagination collection, since it cannot be reliably calculated without a view.(John Wood)
@ -124,9 +125,9 @@
* Major enhancements
* Added a new Rack logger middleware letting you log/save requests/queries (Matt Aimonetti)
* Minor enhancements
* Minor enhancements
* Added #amount_pages to a paginated result array (Matt Aimonetti)
* Ruby 1.9.2 compatible (Matt Aimonetti)
* Added a property? method for property cast as :boolean (John Wood)
@ -135,14 +136,14 @@
* Bug fix: made ExtendedDocument#all compatible with Couch 0.10 (tc)
== 0.32
* Major enhancements
* ExtendedDocument.get doesn't raise an exception anymore. If no documents are found nil is returned.
* ExtendedDocument.get! works the say #get used to work and will raise an exception if a document isn't found.
* Minor enhancements
* Minor enhancements
* Bug fix: Model.all(:keys => [1,2]) was not working (Matt Aimonetti)
* Added ValidationErrors#count in order to play nicely with Rails (Peter Wagenet)
* Bug fix: class proxy design doc refresh (Daniel Kirsh)
@ -155,29 +156,29 @@
* Created an abstraction HTTP layer to support different http adapters (Matt Aimonetti)
* Added ExtendedDocument.create({}) and #create!({}) so you don't have to do Model.new.create (Matt Aimonetti)
* Minor enhancements
* Added an init.rb file for easy usage as a Rails plugin (Aaron Quint)
* Bug fix: pagination shouldn't die on empty results (Arnaud Berthomier)
* Optimized ExtendedDocument.count to run about 3x faster (Matt Aimonetti)
* Added Float casting (Ryan Felton & Matt Aimonetti)
== 0.30
* Major enhancements
* Added support for pagination (John Wood)
* Improved performance when initializing documents with timestamps (Matt Aimonetti)
* Minor enhancements
* Extended the API to retrieve an attachment URI (Matt Aimonetti)
* Bug fix: default value should be able to be set as false (Alexander Uvarov)
* Bug fix: validates_is_numeric should be able to properly validate a Float instance (Rob Kaufman)
* Bug fix: fixed the Timeout implementation (Seth Falcon)
---
Unfortunately, before 0.30 we did not keep a track of the modifications made to CouchRest.

View file

@ -1,25 +1,31 @@
module CouchRest
module Model
module AttributeProtection
# Attribute protection from mass assignment to CouchRest properties
#
# Attribute protection from mass assignment to CouchRest::Model properties
#
# Protected methods will be removed from
# * new
# * new
# * update_attributes
# * upate_attributes_without_saving
# * attributes=
#
# There are two modes of protection
# 1) Declare accessible poperties, assume all the rest are protected
# property :name, :accessible => true
# property :admin # this will be automatically protected
#
# 2) Declare protected properties, assume all the rest are accessible
# property :name # this will not be protected
# There are two modes of protection
# 1) Declare accessible poperties, and assume all unspecified properties are protected
# property :name, :accessible => true
# property :admin # this will be automatically protected
#
# 2) Declare protected properties, and assume all unspecified properties are accessible
# property :name # this will not be protected
# property :admin, :protected => true
#
# Note: you cannot set both flags in a single class
# 3) Mix and match, and assume all unspecified properties are protected.
# property :name, :accessible => true
# property :admin, :protected => true
# property :phone # this will be automatically protected
#
# Note: the timestamps! method protectes the created_at and updated_at properties
def self.included(base)
base.extend(ClassMethods)
end
@ -56,18 +62,13 @@ module CouchRest
private
def properties_to_remove_from_mass_assignment
has_protected = !protected_properties.empty?
has_accessible = !accessible_properties.empty?
to_remove = protected_properties
if !has_protected && !has_accessible
[]
elsif has_protected && !has_accessible
protected_properties
elsif has_accessible && !has_protected
properties.reject { |prop| prop.options[:accessible] }
else
raise "Set either :accessible or :protected for #{self.class}, but not both"
unless accessible_properties.empty?
to_remove += properties.reject { |prop| prop.options[:accessible] }
end
to_remove
end
end
end

View file

@ -23,13 +23,13 @@ describe "Model Attributes" do
user.name.should == "will"
user.phone.should == "555-5555"
end
it "should recreate from the database properly" do
user = NoProtection.new
user.name = "will"
user.phone = "555-5555"
user.save!
user = NoProtection.get(user.id)
user.name.should == "will"
user.phone.should == "555-5555"
@ -50,7 +50,7 @@ describe "Model Attributes" do
end
it "should protect non-accessible properties set through new" do
user = WithAccessible.new(:name => "will", :admin => true)
user = WithAccessible.new(:name => "will", :admin => true)
user.name.should == "will"
user.admin.should == false
@ -79,7 +79,7 @@ describe "Model Attributes" do
end
it "should protect non-accessible properties set through new" do
user = WithProtected.new(:name => "will", :admin => true)
user = WithProtected.new(:name => "will", :admin => true)
user.name.should == "will"
user.admin.should == false
@ -94,15 +94,22 @@ describe "Model Attributes" do
end
end
describe "protected flag" do
class WithBoth < CouchRest::Model::Base
describe "Model Base", "mixing protected and accessible flags" do
class WithBothAndUnspecified < CouchRest::Model::Base
use_database TEST_SERVER.default_database
property :name, :accessible => true
property :admin, :default => false, :protected => true
property :phone, :default => 'unset phone number'
end
it "should raise an error when both are set" do
lambda { WithBoth.new }.should raise_error
it { expect { WithBothAndUnspecified.new }.to_not raise_error }
it 'should assume that any unspecified property is protected by default' do
user = WithBothAndUnspecified.new(:name => 'will', :admin => true, :phone => '555-1234')
user.name.should == 'will'
user.admin.should == false
user.phone.should == 'unset phone number'
end
end
@ -113,7 +120,7 @@ describe "Model Attributes" do
property :admin, :default => false, :protected => true
view_by :name
end
before(:each) do
@user = WithProtected.new
@user.name = "will"
@ -128,12 +135,12 @@ describe "Model Attributes" do
it "Base#get should not strip protected attributes" do
reloaded = WithProtected.get( @user.id )
verify_attrs reloaded
verify_attrs reloaded
end
it "Base#get! should not strip protected attributes" do
reloaded = WithProtected.get!( @user.id )
verify_attrs reloaded
verify_attrs reloaded
end
it "Base#all should not strip protected attributes" do
@ -141,13 +148,13 @@ describe "Model Attributes" do
docs = WithProtected.all(:key => @user.id)
docs.size.should == 1
reloaded = docs.first
verify_attrs reloaded
verify_attrs reloaded
end
it "views should not strip protected attributes" do
docs = WithProtected.by_name(:startkey => "will", :endkey => "will")
reloaded = docs.first
verify_attrs reloaded
verify_attrs reloaded
end
end
end