couch_potato-extensions 0.0.1

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.
@@ -0,0 +1,33 @@
1
+ Some additions/extensions to CouchPotato, because awesome needs more awesome.
2
+
3
+ ### Encrypted attributes
4
+
5
+ A simple way to encrypt specific attributes with a specific password and salt.
6
+ Each attribute can be encrypted differently, by specifying password and salt
7
+ when declaring them.
8
+
9
+ require 'couch_potato'
10
+ require 'couch_potato/extensions'
11
+
12
+ class User
13
+ include CouchPotato::Persistence
14
+ include CouchPotato::Extensions::Encryption
15
+ encrypted\_property :email, :password => "your mum", :salt => "your dad"
16
+ end
17
+
18
+ Of course what's the point if you can't query that stuff? Fret not, help is near:
19
+
20
+ class User
21
+ view :by_email, :key => :email, :type => CouchPotato::Extensions::EncryptedViewSpec
22
+ end
23
+
24
+ CouchPotato.database.view(User.by_email(:key => "paul@example.com"))
25
+
26
+ Easy as pie!
27
+
28
+ Speaking of easy, so far it's both very simple, because that's what I need, only views
29
+ with one key are supported so far.
30
+
31
+ License: MIT baby!
32
+
33
+ Sponsored by [Peritor](http://peritor.com)
@@ -0,0 +1,27 @@
1
+ require 'rake'
2
+ require 'spec/rake/spectask'
3
+
4
+ Spec::Rake::SpecTask.new(:spec) do |t|
5
+ t.spec_files = FileList['spec/*_spec.rb']
6
+ end
7
+
8
+ NAME='couch_potato-extensions'
9
+
10
+ def gemspec_file
11
+ "#{NAME}.gemspec"
12
+ end
13
+
14
+ def gem_file
15
+ "#{NAME}-#{source_version}.gem"
16
+ end
17
+
18
+ def source_version
19
+ line = File.read("lib/#{NAME.gsub(/-/, "/")}.rb")[/^\s*VERSION\s*=\s*.*/]
20
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
21
+ end
22
+
23
+ task :build do
24
+ sh "mkdir -p pkg"
25
+ sh "gem build #{gemspec_file}"
26
+ sh "mv #{gem_file} pkg"
27
+ end
@@ -0,0 +1,10 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/extensions/persistence")
2
+ require File.expand_path(File.dirname(__FILE__) + "/extensions/encryption")
3
+ require File.expand_path(File.dirname(__FILE__) + "/extensions/encrypted_property")
4
+ require File.expand_path(File.dirname(__FILE__) + "/extensions/encrypted_view_spec")
5
+
6
+ module CouchPotato
7
+ module Extensions
8
+ VERSION = '0.0.1'
9
+ end
10
+ end
@@ -0,0 +1,46 @@
1
+ require 'bcrypt'
2
+
3
+ module CouchPotato
4
+ module Extensions
5
+ class EncryptedProperty
6
+ attr_reader :type, :name
7
+
8
+ def initialize(owner, name, options = {})
9
+ @type = owner
10
+ @name = name
11
+ @options = options
12
+
13
+ define_accessors(name)
14
+ end
15
+
16
+ def define_accessors(name)
17
+ type.class_eval do
18
+ define_method(name) do
19
+ instance_variable_get("@#{name}")
20
+ end
21
+
22
+ define_method("#{name}=") do |value|
23
+ instance_variable_set("@#{name}", value)
24
+ end
25
+ end
26
+ end
27
+
28
+ def build(object, json)
29
+ value = json[name.to_s].nil? ? json[name.to_sym] : json[name.to_s]
30
+ object.send "#{name}=", decrypt(value)
31
+ end
32
+
33
+ def serialize(json, object)
34
+ json[name] = encrypt(object.send(name))
35
+ end
36
+
37
+ def encrypt(value)
38
+ Base64.encode64(EzCrypto::Key.encrypt_with_password(@options[:password], @options[:salt], value))
39
+ end
40
+
41
+ def decrypt(value)
42
+ EzCrypto::Key.decrypt_with_password(@options[:password], @options[:salt], Base64.decode64(value))
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,20 @@
1
+ module CouchPotato
2
+ module Extensions
3
+ class EncryptedViewSpec < CouchPotato::View::ModelViewSpec
4
+
5
+ def view_parameters
6
+ parameters = super
7
+ if parameters[:key]
8
+ parameters[:key] = find_and_encrypt_key_attribute(parameters[:key])
9
+ end
10
+ parameters
11
+ end
12
+
13
+ def find_and_encrypt_key_attribute(key)
14
+ property = klass.properties.find{|property| property.name.to_s == options[:key].to_s}
15
+ return key if not property
16
+ property.encrypt(key)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,15 @@
1
+ require 'ezcrypto'
2
+
3
+ module CouchPotato
4
+ module Extensions
5
+ module Encryption
6
+ def self.included(base)
7
+ base.instance_eval do
8
+ def encrypted_property(name, options = {})
9
+ properties << CouchPotato::Extensions::EncryptedProperty.new(self, name, options)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ module CouchPotato
2
+ module Persistence
3
+ def attributes
4
+ self.class.properties.inject({}) do |result, property|
5
+ result[property.name] = send(property.name)
6
+ result
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe CouchPotato::Extensions::EncryptedProperty do
4
+ class SecureDocument
5
+ include CouchPotato::Persistence
6
+ include CouchPotato::Extensions::Encryption
7
+ encrypted_property :body, :salt => 'Va7JYeT7t08vMweYU6F6dO', :password => "coffee! more coffee!"
8
+ end
9
+
10
+ describe "setting up" do
11
+ it "should add the declared property to the internal list" do
12
+ SecureDocument.properties.find()
13
+ end
14
+ end
15
+
16
+ describe "accessing attributes" do
17
+ it "should add attribute accessors" do
18
+ document = SecureDocument.new
19
+ document.respond_to?(:body).should == true
20
+ document.respond_to?(:body=).should == true
21
+ end
22
+
23
+ it "should set the attribute" do
24
+ document = SecureDocument.new(:body => "very important")
25
+ document.body.should == 'very important'
26
+ end
27
+ end
28
+
29
+ describe "saving documents" do
30
+ let(:document) { SecureDocument.new(:body => "very important") }
31
+
32
+ it "should encrypt the property when accessing the document hash" do
33
+ body = document.to_hash[:body]
34
+ body.should_not == nil
35
+ body.should_not == 'very important'
36
+ body.should == Base64.encode64(EzCrypto::Key.encrypt_with_password("coffee! more coffee!", "Va7JYeT7t08vMweYU6F6dO", "very important"))
37
+ end
38
+ end
39
+
40
+ describe "loading documents" do
41
+ let(:document) { SecureDocument.new(:body => "very important") }
42
+
43
+ it "should decrypt the attributes" do
44
+ CouchPotato.database.save_document document
45
+ loaded_document = CouchPotato.database.load_document(document.id)
46
+ loaded_document.body.should == "very important"
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe CouchPotato::Extensions::EncryptedViewSpec do
4
+ class SecureUser
5
+ include CouchPotato::Persistence
6
+ include CouchPotato::Extensions::Encryption
7
+ encrypted_property :email, :salt => 'Va7JYeT7t08vMweYU6F6dO', :password => "coffee! more coffee!"
8
+
9
+ view :by_email, :key => :email, :type => CouchPotato::Extensions::EncryptedViewSpec
10
+ end
11
+
12
+ before(:each) do
13
+ @encrypted_email = Base64.encode64(EzCrypto::Key.encrypt_with_password("coffee! more coffee!", "Va7JYeT7t08vMweYU6F6dO", "paul@example.com"))
14
+ end
15
+
16
+ let(:user) do
17
+ user = SecureUser.new(:email => "paul@example.com")
18
+ CouchPotato.database.save_document(user)
19
+ user
20
+ end
21
+
22
+ it "should encrypt the key before running the view" do
23
+ CouchPotato.database.send(:database).should_receive(:view) do |url, parameters|
24
+ parameters[:key].should == @encrypted_email
25
+ {"rows" => {}}
26
+ end
27
+
28
+ CouchPotato.database.view(SecureUser.by_email(:key => 'paul@example.com'))
29
+ end
30
+
31
+ it "should find documents with an encrypted email" do
32
+ user
33
+ results = CouchPotato.database.view(SecureUser.by_email(:key => 'paul@example.com'))
34
+ results.first.should == user
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require 'couch_potato'
4
+
5
+ $:.unshift(File.expand_path(File.dirname(__FILE__) + "../lib"))
6
+
7
+ CouchPotato::Config.database_name = 'couch_potato-extentions_test'
8
+ def recreate_db
9
+ CouchPotato.couchrest_database.recreate!
10
+ end
11
+ recreate_db
12
+
13
+
14
+ require 'couch_potato/extensions/encryption'
15
+ require 'couch_potato/extensions/encrypted_property'
16
+ require 'couch_potato/extensions/persistence'
17
+ require 'couch_potato/extensions/encrypted_view_spec'
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: couch_potato-extensions
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Mathias Meyer
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-04-12 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: couch_potato
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: ezcrypto
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 0
41
+ version: "0"
42
+ type: :runtime
43
+ version_requirements: *id002
44
+ - !ruby/object:Gem::Dependency
45
+ name: rspec
46
+ prerelease: false
47
+ requirement: &id003 !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ~>
50
+ - !ruby/object:Gem::Version
51
+ segments:
52
+ - 1
53
+ - 2
54
+ - 9
55
+ version: 1.2.9
56
+ type: :development
57
+ version_requirements: *id003
58
+ description: See summary, it says it all, trust me.
59
+ email: meyer@paperplanes.de
60
+ executables: []
61
+
62
+ extensions: []
63
+
64
+ extra_rdoc_files:
65
+ - README.md
66
+ files:
67
+ - Rakefile
68
+ - lib/couch_potato/extensions/encrypted_property.rb
69
+ - lib/couch_potato/extensions/encrypted_view_spec.rb
70
+ - lib/couch_potato/extensions/encryption.rb
71
+ - lib/couch_potato/extensions/persistence.rb
72
+ - lib/couch_potato/extensions.rb
73
+ - spec/encrypted_property_spec.rb
74
+ - spec/encrypted_view_spec.rb
75
+ - spec/spec_helper.rb
76
+ - README.md
77
+ has_rdoc: true
78
+ homepage: http://github.com/mattmatt/couch_potato-extensions
79
+ licenses: []
80
+
81
+ post_install_message:
82
+ rdoc_options:
83
+ - --charset=UTF-8
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ segments:
91
+ - 0
92
+ version: "0"
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ segments:
98
+ - 0
99
+ version: "0"
100
+ requirements: []
101
+
102
+ rubyforge_project:
103
+ rubygems_version: 1.3.6
104
+ signing_key:
105
+ specification_version: 3
106
+ summary: Some extensions for CouchPotato, because more awesome is always a good thing.
107
+ test_files: []
108
+