couch_potato-extensions 0.0.1

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