omelettes 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Mark Sim
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # Omelettes #
2
+
3
+ ## Basic Usage ##
4
+
5
+ gem install omelettes
6
+ rails g omelettes:config
7
+ rake db:cook
8
+
9
+ ## Configuration ##
10
+
11
+ After running 'rails g omelettes:config' you will find a config file in 'config/initializers/omelettes.rb'
12
+
13
+ Omelettes.setup do |config|
14
+ # Ignore tables or columns using strings or regular expressions
15
+ config.ignore_tables = ["schema_migrations", "my_reporting_table", /(a-z_)user/]
16
+ config.ignore_columns = [/(a-z_)*type/i, "name", "city"]
17
+
18
+ # Override non-standard table names => classes like this
19
+ # config.models['admin_users'] = Admin::User
20
+
21
+ # Override model specific columns
22
+
23
+ User.treat(:nickname).as(:name)
24
+ Person.scramble(:street) {|value| "#{value.reverse}"}
25
+
26
+ # Freeze / Ignore columns on specific models
27
+ User.harden(:password)
28
+
29
+ # To make a normally "Faker" obfuscated column behave normally, override with :omelette
30
+ User.scramble(:name).as(:omelette)
31
+
32
+ # To override the model associated with a specific table, make sure and specify it here:
33
+ config.models['logins'] = User
34
+ end
35
+
36
+ By default, the following columns will be Faker-ified (replaced with faker info RATHER than obfuscated using omelettes same-length-and-initial-character)
37
+
38
+ * name
39
+ * first_name
40
+ * last_name
41
+ * city
42
+ * state
43
+ * country
44
+ * street_address
45
+ * street_name
46
+ * zip_code
47
+ * company_name
48
+ * company
49
+ * email
50
+ * user_name
51
+ * phone
52
+
53
+ And the following can be used to 'treat' a column 'as':
54
+ * paragraph
55
+ * paragraphs
56
+ * sentence
57
+ * sentences
58
+ * words
59
+
60
+ You can also keep model-level configurations within the model itself
61
+
62
+ class User < ActiveRecord::Base
63
+ treat(:login).as(:user_name)
64
+ ignore :password
65
+ end
66
+
67
+ ## About ##
68
+
69
+ omelettets is obfuscated 'obfuscate'. Omelettes takes strings in your database and replaces them with worlds of the same length and same initial letter.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc "Run RSpec"
6
+ RSpec::Core::RakeTask.new do |t|
7
+ t.verbose = false
8
+ end
9
+
10
+ task :default => :spec
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'omelettes'
@@ -0,0 +1,2 @@
1
+ Description:
2
+ The omelettes:config generator creates the omelettes.rb config file in the initializers directory.
@@ -0,0 +1,11 @@
1
+ module Omelettes
2
+ module Generators
3
+ class ConfigGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ def generate_config
7
+ copy_file "omelettes.rb", "config/initializers/omelettes.rb"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ # Omelettes Obfuscation Setup
2
+ #
3
+ # Columns with the following names will be automatically Faker-ified.
4
+ # You can make columns with other names Faker-ified by overriding the model
5
+ # specific columns a la: User.scramble(:nickname).as(:first_name)
6
+ #
7
+ # :name, :first_name, :last_name
8
+ # :city, :state, :country, :street_address, :street_name, :zip_code
9
+ # :company_name, :company, :email, :user_name, :phone
10
+ # :paragraph, :paragraphs, :sentence, :sentences, :words
11
+
12
+ Omelettes.setup do |config|
13
+ # Ignore tables or columns using strings or regular expressions
14
+ # config.ignore_tables = ["schema_migrations", "my_reporting_table", /(a-z_)user/]
15
+ # config.ignore_columns = [/(a-z_)*type/i, "name", "city"]
16
+
17
+ config.ignore_columns = [/[a-z_]*type/i, /[a-z_]*password[a-z_]*/i]
18
+ config.ignore_tables = ['schema_migrations']
19
+
20
+ # Override non-standard table names => classes like this
21
+ # config.models['admin_users'] = Admin::User
22
+
23
+ # Override model specific columns
24
+ # User.scramble(:nickname).as(:name)
25
+ # Person.scramble(:street) {|value| "#{value.reverse}"}
26
+ # Freeze / Ignore columns on specific models
27
+ # User.harden(:password)
28
+ # To make a normally "Faker" obfuscated column behave normally, override with :omelette
29
+ # User.scramble(:name).as(:omelette)
30
+ end
@@ -0,0 +1,48 @@
1
+ require 'faker'
2
+
3
+ module Omelettes
4
+ class Column
5
+ attr_accessor :name, :style, :custom_block
6
+ def initialize(name, style=nil, &block)
7
+ @name = name
8
+ @style = style
9
+ @custom_block = block
10
+ end
11
+
12
+ def process(string)
13
+ if @custom_block
14
+ return @custom_block.call(string)
15
+ else
16
+ Column.default(@style || @name, string)
17
+ end
18
+ end
19
+
20
+ def self.default(name, value)
21
+ name = name.downcase.to_sym
22
+ case name
23
+ when :hardened
24
+ return value
25
+ when :name, :first_name, :last_name
26
+ return Faker::Name.send(name)
27
+ when :city, :state, :country, :street_address, :street_name, :zip_code
28
+ return Faker::Address.send(name)
29
+ when :company_name, :company
30
+ return Faker::Company.name
31
+ when :email, :user_name
32
+ return Faker::Internet.send(name)
33
+ when :paragraph, :paragraphs, :sentence, :sentences, :words
34
+ return Faker::Lorem.send(name)
35
+ when :phone
36
+ return Faker::PhoneNumber.phone_number
37
+ else
38
+ return Omelettes::Obfuscate.obfuscate(value)
39
+ end
40
+ end
41
+
42
+ def as(style)
43
+ @style = style unless @style == :hardened
44
+ self
45
+ end
46
+ alias :like :as
47
+ end
48
+ end
@@ -0,0 +1,45 @@
1
+ module Omelettes
2
+ module ModelAdditions
3
+ module ClassMethods
4
+ def column_config(column_name)
5
+ @column_config ||= {}
6
+ @column_config[column_name.to_s]
7
+ end
8
+
9
+ def treat(column_name, style=nil, &block)
10
+ @column_config ||= {}
11
+ column = Column.new(column_name, style, &block)
12
+ @column_config[column_name.to_s] = column
13
+ column
14
+ end
15
+ alias :scramble :treat
16
+
17
+ def ignore(column_name)
18
+ @column_config ||= {}
19
+ column = Column.new(column_name, :hardened)
20
+ @column_config[column_name.to_s] = column
21
+ column
22
+ end
23
+ alias :harden :ignore
24
+ end
25
+
26
+ def obfuscate(column_name)
27
+ column = self.class.column_config(column_name)
28
+ original_value = self.send(column_name)
29
+ if column
30
+ value = column.process(original_value)
31
+ else
32
+ value = Column.default(column_name, original_value)
33
+ end
34
+ self.update_attribute(column_name, value) if original_value != value
35
+ end
36
+
37
+ def self.included(base)
38
+ base.extend ClassMethods
39
+ end
40
+ end
41
+ end
42
+
43
+ ActiveRecord::Base.class_eval do
44
+ include Omelettes::ModelAdditions
45
+ end
@@ -0,0 +1,64 @@
1
+ module Omelettes
2
+ class Obfuscate
3
+ class << self
4
+ def cook(silent=false)
5
+ total_tables = 0
6
+ total_attributes = 0
7
+ Words.load(word_list || "/usr/share/dict/words")
8
+ tables.each do |table|
9
+ next if ignore_table?(table)
10
+ print "\nProcessing #{model(table).name}" unless silent
11
+ model(table).find_each do |object|
12
+ model(table).columns.each do |column|
13
+ next if ignore_column?(column.name) || column.type != :string
14
+ object.obfuscate(column.name)
15
+ total_attributes += 1
16
+ end
17
+ print "." unless silent
18
+ end
19
+ total_tables += 1
20
+ end
21
+ print "\n" unless silent
22
+ [total_tables, total_attributes]
23
+ end
24
+
25
+ def tables
26
+ ActiveRecord::Base.connection.tables
27
+ end
28
+
29
+ def model(table)
30
+ self.models ||= {}
31
+ self.models[table] ||= table.camelcase.singularize.constantize
32
+ self.models[table]
33
+ end
34
+
35
+ def ignore_table?(table)
36
+ ignore_tables.each do |ignore|
37
+ return true if table.match(ignore).to_s == table
38
+ end
39
+ false
40
+ end
41
+
42
+ def ignore_column?(column)
43
+ ignore_columns.each do |ignore|
44
+ return true if column.match(ignore).to_s == column
45
+ end
46
+ false
47
+ end
48
+
49
+ def obfuscate(string)
50
+ return nil if string.nil?
51
+ result = []
52
+ string.split(/(\s+)|([[:punct:]])/).each do |word|
53
+ result << (word.match(/[a-zA-Z]+/).nil? ? word : Words.replace(word))
54
+ end
55
+ result.join("")
56
+ end
57
+
58
+ attr_accessor :ignore_tables
59
+ attr_accessor :ignore_columns
60
+ attr_accessor :word_list
61
+ attr_accessor :models
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,10 @@
1
+ require 'omelettes'
2
+ require 'rails'
3
+
4
+ module Omelettes
5
+ class Railtie < Rails::Railtie
6
+ rake_tasks do
7
+ load "tasks/omelettes.rake"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,36 @@
1
+ module Omelettes
2
+ class Words
3
+ class << self
4
+
5
+ def word_hash
6
+ @word_hash ||= {}
7
+ end
8
+
9
+ def add(word)
10
+ key = "#{word[0].downcase}#{word.length}"
11
+ @word_hash[key] ||= []
12
+ @word_hash[key] << word
13
+ end
14
+
15
+ def replace(word)
16
+ key = "#{word[0].downcase}#{word.length}"
17
+ valid_words = (@word_hash[key] || [])
18
+ new_word = valid_words[rand(valid_words.size)]
19
+ return new_word.send(word[0].upcase == word[0] ? :capitalize : :downcase) unless new_word.nil?
20
+ word
21
+ end
22
+
23
+ def load(path="/usr/share/dict/words")
24
+ clear
25
+ (path.is_a?(Array) ? path : File.readlines(path)).each do |word|
26
+ add(word.strip)
27
+ end
28
+ end
29
+
30
+ def clear
31
+ @word_hash = {}
32
+ end
33
+ end
34
+ end
35
+
36
+ end
data/lib/omelettes.rb ADDED
@@ -0,0 +1,19 @@
1
+ begin
2
+ require 'active_record'
3
+ rescue LoadError
4
+ require 'activerecord' unless defined?(ActiveRecord)
5
+ end
6
+
7
+ require 'omelettes/column'
8
+ require 'omelettes/model_additions'
9
+ require 'omelettes/obfuscate'
10
+ require 'omelettes/words'
11
+
12
+ module Omelettes
13
+ require 'omelettes/railtie' if defined?(Rails)
14
+
15
+ def self.setup
16
+ Omelettes::Obfuscate.models = {}
17
+ yield Omelettes::Obfuscate
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ namespace :db do
2
+ desc "Obfuscate the database with Omelettes"
3
+ task :cook => :environment do
4
+ print "Are you sure you want to scramble all strings in the database? (y/n): "
5
+ input = $stdin.gets.strip
6
+ if input == "y"
7
+ Omelettes::Obfuscate.cook
8
+ end
9
+ end
10
+ end
data/spec/README.rdoc ADDED
@@ -0,0 +1,10 @@
1
+ = Omelettes Specs
2
+
3
+ == Running the specs
4
+
5
+ To run the specs first run the +bundle+ command to install the necessary gems and the +rake+ command to run the specs.
6
+
7
+ bundle
8
+ rake
9
+
10
+ The specs currently require Ruby 1.9.2
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe Omelettes::Column do
4
+ describe "creation" do
5
+ it "accepts a name" do
6
+ c = nil
7
+ lambda { c = Omelettes::Column.new(:name) }.should_not raise_error
8
+ c.name.should == :name
9
+ end
10
+
11
+ it "accepts a name and an optional style" do
12
+ c = nil
13
+ lambda { c = Omelettes::Column.new(:name, :city) }.should_not raise_error
14
+ c.name.should == :name
15
+ c.style.should == :city
16
+ end
17
+
18
+ it "accepts a block" do
19
+ c = Omelettes::Column.new(:name) {|value| value.reverse}
20
+ c.custom_block.should_not be_nil
21
+ end
22
+
23
+ it "allows 'as' or 'like' syntax to alter the style" do
24
+ Omelettes::Column.new(:name).as(:test).style.should == :test
25
+ Omelettes::Column.new(:value).like(:key).style.should == :key
26
+ end
27
+ end
28
+
29
+ describe "process" do
30
+ it "executes a block if present" do
31
+ c = Omelettes::Column.new(:name) {|value| value.reverse}
32
+ c.process("eggs").should == "sgge"
33
+ end
34
+
35
+ it "calls the default processing method if no block present" do
36
+ c = Omelettes::Column.new(:name)
37
+ Faker::Name.should_receive(:name).once
38
+ c.process("Mark")
39
+ end
40
+
41
+ it "calls the passed 'style' if passed, overriding the name" do
42
+ c = Omelettes::Column.new(:name).as(:paragraph)
43
+ Faker::Lorem.should_receive(:paragraph).once
44
+ c.process("Some stuff")
45
+ end
46
+
47
+ it "calls the standard obfuscation method if the style is not recognized" do
48
+ c = Omelettes::Column.new(:name).as(:omelettes)
49
+ Omelettes::Obfuscate.should_receive(:obfuscate).once
50
+ c.process("Some Stuff")
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Model Additions" do
4
+ describe "treat / scramble" do
5
+ it "should create a column with a specified style for a model" do
6
+ User.treat(:middle_name).as(:first_name)
7
+ User.column_config(:middle_name).style.should == :first_name
8
+ end
9
+
10
+ it "should create a column with a custom block specified for a model" do
11
+ User.scramble(:middle_name) {|value| value.reverse}
12
+ User.column_config(:middle_name).custom_block.should_not be_nil
13
+ end
14
+ end
15
+
16
+ describe "ignore / harden" do
17
+ it "should create a column with a style of ':hardened'" do
18
+ User.ignore(:middle_name)
19
+ User.column_config(:middle_name).style.should == :hardened
20
+ end
21
+
22
+ it "should not be overwritten with 'as'" do
23
+ User.ignore(:middle_name).as(:first_name)
24
+ User.column_config(:middle_name).style.should == :hardened
25
+ end
26
+ end
27
+
28
+ describe "obfuscate" do
29
+ before(:each) do
30
+ @user = User.new
31
+ @user.stub(:first_name).and_return("Ed")
32
+ @user.stub(:middle_name).and_return("Jeremy")
33
+ @user.stub(:last_name).and_return("Stevens")
34
+ @user.stub(:city).and_return("Stuckeyville")
35
+ User.stub(:find_each).and_return([@user])
36
+ end
37
+
38
+ it "should process the column result back to the database" do
39
+ User.treat(:middle_name).as(:first_name)
40
+ @user.should_receive(:update_attribute).once
41
+ @user.obfuscate(:middle_name)
42
+ end
43
+
44
+ it "should not write anything to the database if the column is ignored" do
45
+ User.ignore(:city)
46
+ @user.should_not_receive(:update_attribute)
47
+ @user.obfuscate(:city)
48
+ end
49
+
50
+ it "should call the passed block and write the result to the database" do
51
+ User.treat(:last_name) {|value| "Vessy"}
52
+ @user.should_receive(:update_attribute).with(:last_name, "Vessy").once
53
+ @user.obfuscate(:last_name)
54
+ end
55
+
56
+ it "should call Faker for default column names, even if not explicitly configured" do
57
+ Faker::Name.should_receive(:first_name).once
58
+ @user.should_receive(:update_attribute).once
59
+ @user.obfuscate(:first_name)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+
3
+ describe Omelettes::Obfuscate do
4
+
5
+ describe "models" do
6
+ it "allows for override" do
7
+ Omelettes.setup do |config|
8
+ config.models['logins'] = User
9
+ end
10
+
11
+ Omelettes::Obfuscate.model("logins").should == User
12
+ end
13
+
14
+ it "returns the model" do
15
+ Omelettes::Obfuscate.model("users").should == User
16
+ end
17
+ end
18
+
19
+ describe "ignore tables" do
20
+ it "ignores matching strings" do
21
+ Omelettes.setup do |config|
22
+ config.ignore_tables = ["alpha", "beta", "kappa"]
23
+ end
24
+
25
+ Omelettes::Obfuscate.ignore_table?("alpha").should be_true
26
+ Omelettes::Obfuscate.ignore_table?("beta").should be_true
27
+ Omelettes::Obfuscate.ignore_table?("kappa").should be_true
28
+ Omelettes::Obfuscate.ignore_table?("delta").should be_false
29
+ end
30
+
31
+ it "ignores matching regex" do
32
+ Omelettes.setup do |config|
33
+ config.ignore_tables = [/[a-z_]*type/i]
34
+ end
35
+
36
+ Omelettes::Obfuscate.ignore_table?("type").should be_true
37
+ Omelettes::Obfuscate.ignore_table?("my_favorite_type").should be_true
38
+ Omelettes::Obfuscate.ignore_table?("matype").should be_true
39
+ Omelettes::Obfuscate.ignore_table?("typedef").should be_false
40
+ Omelettes::Obfuscate.ignore_table?("another").should be_false
41
+ end
42
+ end
43
+
44
+ describe "ignore columns" do
45
+ it "ignores matching strings" do
46
+ Omelettes.setup do |config|
47
+ config.ignore_columns = ["alpha", "beta", "kappa"]
48
+ end
49
+
50
+ Omelettes::Obfuscate.ignore_column?("alpha").should be_true
51
+ Omelettes::Obfuscate.ignore_column?("beta").should be_true
52
+ Omelettes::Obfuscate.ignore_column?("kappa").should be_true
53
+ Omelettes::Obfuscate.ignore_column?("delta").should be_false
54
+ end
55
+
56
+ it "ignores matching regex" do
57
+ Omelettes.setup do |config|
58
+ config.ignore_columns = [/[a-z_]*type/i]
59
+ end
60
+
61
+ Omelettes::Obfuscate.ignore_column?("type").should be_true
62
+ Omelettes::Obfuscate.ignore_column?("my_favorite_type").should be_true
63
+ Omelettes::Obfuscate.ignore_column?("matype").should be_true
64
+ Omelettes::Obfuscate.ignore_column?("typedef").should be_false
65
+ Omelettes::Obfuscate.ignore_column?("another").should be_false
66
+ end
67
+ end
68
+
69
+ describe "obfuscate" do
70
+ it "returns nil if passed nil" do
71
+ Omelettes::Obfuscate.obfuscate(nil).should be_nil
72
+ end
73
+
74
+ it "replaces words" do
75
+ Omelettes::Words.clear
76
+ ["barfs", "foo", "queen", "tad"].each do |word|
77
+ Omelettes::Words.add(word)
78
+ end
79
+ Omelettes::Obfuscate.obfuscate("the quick brown fox").should == "tad queen barfs foo"
80
+ end
81
+
82
+ it "preserves punctuation" do
83
+ Omelettes::Words.clear
84
+ ["barfs", "foo", "queen", "tad"].each do |word|
85
+ Omelettes::Words.add(word)
86
+ end
87
+ Omelettes::Obfuscate.obfuscate("the: quick, brown! fox :)").should == "tad: queen, barfs! foo :)"
88
+ end
89
+ end
90
+
91
+ describe "cook" do
92
+ before(:each) do
93
+ Omelettes.setup do |config|
94
+ config.word_list = %w(barfs foo queen tad pole)
95
+ end
96
+
97
+ Omelettes::Obfuscate.stub(:tables).and_return(["users"])
98
+
99
+ User.stub(:find_each).and_return(User.new(:first_name => "Mark", :last_name => "Sim", :city => "Austin"))
100
+ end
101
+
102
+ it "ignores specified tables" do
103
+ Omelettes::Obfuscate.ignore_tables = ["users"]
104
+ Omelettes::Obfuscate.cook(true).should == [0, 0]
105
+ end
106
+
107
+ it "ignores specified columns" do
108
+ Omelettes::Obfuscate.ignore_tables = []
109
+ Omelettes::Obfuscate.ignore_columns = ['first_name', 'middle_name', 'last_name', 'city']
110
+ Omelettes::Obfuscate.cook(true).should == [1, 0]
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe Omelettes::Words do
4
+ describe "load" do
5
+ it "loads from the default path" do
6
+ Omelettes::Words.clear
7
+ Omelettes::Words.word_hash.should == {}
8
+ Omelettes::Words.load
9
+ Omelettes::Words.word_hash.should_not == {}
10
+ Omelettes::Words.word_hash.should_not be_nil
11
+
12
+ end
13
+
14
+ it "optionally accepts a load path" do
15
+ File.should_receive(:readlines).once.and_return(["one"])
16
+ Omelettes::Words.load("test.path")
17
+ Omelettes::Words.word_hash.should == {"o3" => ["one"]}
18
+ end
19
+ end
20
+
21
+ describe "add" do
22
+ before(:each) do
23
+ Omelettes::Words.clear
24
+ end
25
+ it "adds a word to the values of the word_hash" do
26
+ Omelettes::Words.add("fate")
27
+ Omelettes::Words.word_hash.values.flatten.should include("fate")
28
+ end
29
+
30
+ it "indexes based on word length and first letter" do
31
+ Omelettes::Words.add("tony")
32
+ Omelettes::Words.word_hash["t4"].should include("tony")
33
+ end
34
+
35
+ it "does not care the case" do
36
+ Omelettes::Words.add("FaT")
37
+ Omelettes::Words.word_hash["f3"].should include("FaT")
38
+ end
39
+ end
40
+
41
+ describe "replace" do
42
+ before(:each) do
43
+ Omelettes::Words.clear
44
+ end
45
+
46
+ it "returns a word of the same length" do
47
+ Omelettes::Words.add("bra")
48
+ Omelettes::Words.add("brak")
49
+ Omelettes::Words.add("brake")
50
+
51
+ Omelettes::Words.replace("bat").should == "bra"
52
+ end
53
+
54
+ it "returns a word starting with the same letter" do
55
+ Omelettes::Words.add("abc")
56
+ Omelettes::Words.add("bcd")
57
+ Omelettes::Words.add("cde")
58
+
59
+ Omelettes::Words.replace("att").should == "abc"
60
+ end
61
+
62
+ it "returns itself if there is no word in the dictionary matching the first letter and length" do
63
+ Omelettes::Words.add("bra")
64
+ Omelettes::Words.add("cake")
65
+ Omelettes::Words.add("brake")
66
+
67
+ Omelettes::Words.replace("bork").should == "bork"
68
+ end
69
+ end
70
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --backtrace
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+ require 'omelettes'
3
+
4
+ RSpec.configure do |config|
5
+ end
6
+
7
+ class TablelessModel < ActiveRecord::Base
8
+ def self.columns() @columns ||= []; end
9
+
10
+ def self.column(name, sql_type = nil, default = nil, null = true)
11
+ columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
12
+ end
13
+
14
+ end
15
+
16
+ class User < TablelessModel
17
+ column :id, :integer
18
+ column :first_name, :string
19
+ column :middle_name, :string
20
+ column :last_name, :string
21
+ column :city, :string
22
+ column :age, :integer
23
+ end
24
+
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omelettes
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.2.0
6
+ platform: ruby
7
+ authors:
8
+ - Mark Sim
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-07-27 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: 2.1.0
24
+ type: :development
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: faker
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 0.9.5
35
+ type: :runtime
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: activerecord
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: "3.0"
46
+ type: :runtime
47
+ version_requirements: *id003
48
+ description: Low-to-no configuration solution for obfuscating sensitive data in your database.
49
+ email: mark@quarternotecoda.com
50
+ executables: []
51
+
52
+ extensions: []
53
+
54
+ extra_rdoc_files: []
55
+
56
+ files:
57
+ - lib/generators/omelettes/config/config_generator.rb
58
+ - lib/generators/omelettes/config/templates/omelettes.rb
59
+ - lib/generators/omelettes/config/USAGE
60
+ - lib/omelettes/column.rb
61
+ - lib/omelettes/model_additions.rb
62
+ - lib/omelettes/obfuscate.rb
63
+ - lib/omelettes/railtie.rb
64
+ - lib/omelettes/words.rb
65
+ - lib/omelettes.rb
66
+ - lib/tasks/omelettes.rake
67
+ - spec/omelettes/column_spec.rb
68
+ - spec/omelettes/model_additions_spec.rb
69
+ - spec/omelettes/obfuscate_spec.rb
70
+ - spec/omelettes/words_spec.rb
71
+ - spec/README.rdoc
72
+ - spec/spec.opts
73
+ - spec/spec_helper.rb
74
+ - Gemfile
75
+ - LICENSE
76
+ - Rakefile
77
+ - README.md
78
+ - init.rb
79
+ homepage: http://github.com/marksim/omelettes
80
+ licenses: []
81
+
82
+ post_install_message:
83
+ rdoc_options: []
84
+
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: "0"
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: 1.3.4
99
+ requirements: []
100
+
101
+ rubyforge_project: omelettes
102
+ rubygems_version: 1.8.4
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Database obfuscation.
106
+ test_files: []
107
+