atheneum 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9dee1c4b05491234603c1a15261ed81340af57c0
4
+ data.tar.gz: 509d97ddd98bfba60f7ee36514a17478ed7c651d
5
+ SHA512:
6
+ metadata.gz: 691ec9670f1f3e9cd80e5e3979a4df8fb3b4696fe21064adaf0eda0976d88cd7974cbc960ac9ec5612993078cab14fde09eb322fea62313989fa3fab72c165fb
7
+ data.tar.gz: 8ddea8d1d9137b75e2fcad952721bdc587d1e12754b9765a21d132cbc18c966ed368c9df215201358d4628578b59e97d365c21c11278add919f6bbff2bc89b6e
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in atheneum.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Peter
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,170 @@
1
+ # Atheneum
2
+ > *noun* **place where records are stored**
3
+
4
+ ## Installation
5
+
6
+ Add this line to your application's Gemfile:
7
+
8
+ ```ruby
9
+ gem 'atheneum'
10
+ ```
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install atheneum
19
+
20
+ ## Usage
21
+ ### Basic#
22
+
23
+ You have a user record, it's always a user, that has a password. There is a `crypted_password` field on your model from the database. Atheneum can use the crypt strategy to take care of storing and retrieving the password. It will also privatise the original attribute accessors so the objects public interface is only the new attribute accessors.
24
+
25
+ **NB: you must also include bcrypt in your gems for this example**
26
+
27
+ ```rb
28
+ class UserRecord < Struct.new(:crypted_password)
29
+ include Atheneum.crypt(:password)
30
+ end
31
+
32
+ user_record = UserRecord.new
33
+ user_record.password = 'password'
34
+ puts user
35
+ # => #<struct UserRecord crypted_password="$2a$10$0lScjOJwCUVdtqGrtIgww.RbvVWXGPD.oISi4DBcIgK3f3YO66aju">
36
+
37
+ user_record.password == 'password'
38
+ # => true
39
+
40
+ user_record.crypted_password
41
+ # => NoMethodError: private method `crypted_password' called for #<UserRecord:0x0000000236f9f0>
42
+
43
+
44
+ # Without Atheneum
45
+ class UserRecord < Struct.new(:crypted_password)
46
+ def password=(password)
47
+ self.crypted_password = BCrypt::Password.create(password).to_s
48
+ end
49
+
50
+ def password
51
+ BCrypt::Password.new(crypted_password)
52
+ end
53
+
54
+ private :crypted_password, :crypted_password=
55
+ end
56
+ ```
57
+ #### Options
58
+
59
+ Storage methods accept more than one attribute. They also take an optional configuration hash
60
+
61
+ - **privatise** *(default: true)* Sets whether existing accessors should privatised
62
+
63
+ - **prefix** Overwrites the strategies default prefix
64
+
65
+ Strategies with no default prefix will use the strategies name eg `SomeStrategy` => `some_strategy`
66
+
67
+ #### New Storage Strategy
68
+
69
+ Say you wanted some strings to be reversed before adding to the database. Perhaps exceptionally mild security.
70
+
71
+ Atheneum looks up strategy classes namespaced under `Atheneum::Strategy`. These need to implement a pack and unpack method as well as optionally generating the storage location
72
+
73
+ ```rb
74
+ module Atheneum
75
+ class Strategy
76
+ class Reverse < Base
77
+
78
+ def pack(item)
79
+ item.reverse
80
+ end
81
+
82
+ def unpack(item)
83
+ item.reverse
84
+ end
85
+
86
+ end
87
+ end
88
+ end
89
+
90
+ class LocationRecord < Struct.new(:obscured_address, :obscured_name)
91
+ include Atheneum.reverse :address, :name, :prefix => 'obscured', :privatise => false
92
+ end
93
+
94
+ location_record = LocationRecord.new
95
+
96
+ location_record.name = 'office'
97
+
98
+ location_record.obscured_name
99
+ # => "eciffo"
100
+ ```
101
+
102
+ ## Why?
103
+
104
+ By privatising the existing attributes then the record object can remain an *immaculate record*, it appears to have only getters and setters. This is an example of how I have been using them. The example is with sequel, I have yet to try with active record but the priciple should hold.
105
+
106
+ ```rb
107
+ require "sequel"
108
+ require "atheneum"
109
+ require "bcrypt"
110
+
111
+ # connect to an in-memory database
112
+ DB = Sequel.sqlite
113
+
114
+ # create an users table
115
+ DB.create_table :users do
116
+ primary_key :id
117
+ String :email
118
+ String :crypted_password
119
+ end
120
+
121
+ # create a user record
122
+ class UserRecord < Sequel::Model(:users)
123
+ Atheneum.crypt :password
124
+ end
125
+
126
+ # create a user model
127
+ class User < SimpleDelegator
128
+
129
+ def check_password(candidate_password)
130
+ password == candidate_password
131
+ end
132
+
133
+ private
134
+
135
+ def model
136
+ __getobj__
137
+ end
138
+
139
+ end
140
+
141
+ # In production
142
+ user = User.new(UserRecord.new)
143
+ user.password = 'password'
144
+ user.check_password('password')
145
+ # => true
146
+
147
+ # In test
148
+ TestRecord = Struct.new(:email, :password)
149
+ user = User.new(TestRecord.new)
150
+ user.password = 'password'
151
+ user.check_password('password')
152
+ # => true
153
+ ```
154
+
155
+ #### Immaculate Record
156
+
157
+ An immaculate record is one that acts purely as a data structure. In practise this works for all classes that can be proxied with a Struct/OpenStruct. Its value is in
158
+
159
+ - Separating all buisness logic from state
160
+
161
+ - fast tests
162
+
163
+
164
+ ## Contributing
165
+
166
+ 1. Fork it ( https://github.com/[my-github-username]/atheneum/fork )
167
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
168
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
169
+ 4. Push to the branch (`git push origin my-new-feature`)
170
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ Dir.glob('tasks/**/*.rake').each(&method(:import))
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'atheneum/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "atheneum"
8
+ spec.version = Atheneum::VERSION
9
+ spec.authors = ["Peter"]
10
+ spec.email = ["peterhsaxton@gmail.com"]
11
+ spec.summary = %q{A micro gem for the immaculate inclusion of BCrypt protected data for example passwords}
12
+ spec.description = %q{Simply declare attributes that require obscuring and that will make it so.
13
+ Useful in exposing buisness logic in objects that use BCrypt
14
+ This gem currently assumes that BCrypt is available rather than adding it as a dependency,
15
+ future versions might support general strategies.
16
+ }
17
+ spec.homepage = ""
18
+ spec.license = "MIT"
19
+
20
+ spec.files = `git ls-files -z`.split("\x0")
21
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
+ spec.require_paths = ["lib"]
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.7"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "minitest", "~> 5.4.3"
28
+ spec.add_development_dependency "minitest-reporters", "~> 1.0.6"
29
+ spec.add_development_dependency "bcrypt", "~> 3.1.9"
30
+ end
@@ -0,0 +1,12 @@
1
+ require "atheneum/version"
2
+ require "atheneum/errors"
3
+ require "atheneum/strategy"
4
+ require "atheneum/storage"
5
+
6
+ module Atheneum
7
+ def self.method_missing(strategy, *attributes, &block)
8
+ options = attributes.pop if attributes.last.class == Hash
9
+ options ||= {}
10
+ Storage.generate strategy, attributes, options
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module Atheneum
2
+ StrategyUndefined = Class.new(StandardError)
3
+ end
@@ -0,0 +1,44 @@
1
+ module Atheneum
2
+
3
+ class Storage
4
+ def initialize(strategy)
5
+ @strategy = strategy
6
+ end
7
+
8
+ attr_reader :strategy
9
+
10
+ def for(records)
11
+ make_module(records, strategy)
12
+ end
13
+
14
+ def make_module(records, strategy)
15
+ Module.new do
16
+ records.each do |record|
17
+ define_method "#{record}=", ->(item){
18
+ self.send "#{strategy.store_for(record)}=", strategy.pack(item)
19
+ }
20
+
21
+ define_method record, -> (){
22
+ strategy.unpack(self.send("#{strategy.store_for(record)}"))
23
+ }
24
+ end
25
+
26
+ if strategy.privatise?
27
+ define_singleton_method :'included', ->(klass){
28
+ records.each do |record|
29
+ klass.send :private, strategy.store_for(record)
30
+ klass.send :private, "#{strategy.store_for(record)}="
31
+ end
32
+ }
33
+ end
34
+
35
+ end
36
+ end
37
+
38
+ def self.generate strategy_name, attributes, options
39
+ strategy = Strategy.find strategy_name
40
+ storage = new strategy.new(options)
41
+ storage.for attributes
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ require_relative './strategy/reverse'
2
+ require_relative './strategy/upper_case'
3
+ require_relative './strategy/crypt'
4
+
5
+ module Atheneum
6
+ class Strategy
7
+ def self.find(name)
8
+ nodule = constantize(name)
9
+ begin
10
+ const_get(nodule)
11
+ rescue NameError
12
+ raise StrategyUndefined.new "Strategy \"#{nodule}\" not found"
13
+ end
14
+ end
15
+
16
+ def self.constantize(string)
17
+ string.to_s.split('_').map(&:capitalize).join
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ module Atheneum
2
+ class Strategy
3
+ class Base < Struct.new(:options)
4
+
5
+ def store_for(attribute)
6
+ "#{prefix}_#{attribute}"
7
+ end
8
+
9
+ def prefix
10
+ options.fetch(:prefix){
11
+ default_prefix
12
+ }
13
+ end
14
+
15
+ def default_prefix
16
+ str = self.class.name.split('::').last.split(/(?=[A-Z])/).map(&:downcase).join('_')
17
+ str[-1, 1] == 'e' ? str + 'd' : str + 'ed'
18
+ end
19
+
20
+ def privatise?
21
+ options.fetch(:privatise) { true }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ module Atheneum
2
+ class Strategy
3
+ class Crypt < Base
4
+ def pack(string)
5
+ BCrypt::Password.create(string).to_s
6
+ end
7
+
8
+ def unpack(crypted_record)
9
+ BCrypt::Password.new(crypted_record)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ require_relative './base'
2
+
3
+ module Atheneum
4
+ class Strategy
5
+ class UpperCase < Base
6
+ def pack(item)
7
+ item.upcase
8
+ end
9
+
10
+ def unpack(item)
11
+ item.downcase
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require_relative './base'
2
+
3
+ module Atheneum
4
+ class Strategy
5
+ class Reverse < Base
6
+ def pack(item)
7
+ item.reverse
8
+ end
9
+
10
+ def unpack(item)
11
+ item.reverse
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module Atheneum
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,16 @@
1
+ require 'rake/testtask'
2
+
3
+ test_tasks = Dir['test/*/'].map { |d| File.basename(d) }
4
+
5
+ test_tasks.each do |folder|
6
+ Rake::TestTask.new("test:#{folder}") do |test|
7
+ test.pattern = "test/#{folder}/**/*_test.rb"
8
+ test.verbose = true
9
+ end
10
+ end
11
+
12
+ desc "Run application test suite"
13
+ Rake::TestTask.new("test") do |test|
14
+ test.pattern = "test/**/*_test.rb"
15
+ test.verbose = true
16
+ end
@@ -0,0 +1,112 @@
1
+ require_relative '../test_config'
2
+
3
+ class AtheneumTest < MiniTest::Test
4
+ def test_raises_error_for_undefined_strategy
5
+ err = assert_raises Atheneum::StrategyUndefined do
6
+ Atheneum.no_strategy
7
+ end
8
+ assert_match(/NoStrategy/, err.message)
9
+ end
10
+
11
+ def test_can_store_a_password_reversed
12
+ dummy_class = Struct.new(:reversed_password)
13
+ dummy_class = dummy_class.include Atheneum.reverse :password
14
+ store = dummy_class.new
15
+ store.password = 'password'
16
+ assert_equal 'password'.reverse, store.send(:reversed_password)
17
+ end
18
+
19
+ def test_can_retrieve_a_password_reversed
20
+ dummy_class = Struct.new(:reversed_password)
21
+ dummy_class = dummy_class.include Atheneum.reverse :password
22
+ store = dummy_class.new 'password'.reverse
23
+ assert_equal 'password', store.password
24
+ end
25
+
26
+ def test_can_store_a_other_reversed
27
+ dummy_class = Struct.new(:reversed_other)
28
+ dummy_class = dummy_class.include Atheneum.reverse :other
29
+ store = dummy_class.new
30
+ store.other = 'other'
31
+ assert_equal 'other'.reverse, store.send(:reversed_other)
32
+ end
33
+
34
+ def test_can_retrieve_a_other_reversed
35
+ dummy_class = Struct.new(:reversed_other)
36
+ dummy_class = dummy_class.include Atheneum.reverse :other
37
+ store = dummy_class.new 'other'.reverse
38
+ assert_equal 'other', store.other
39
+ end
40
+
41
+ def test_can_store_a_item_upper_cased
42
+ dummy_class = Struct.new(:upper_cased_item)
43
+ dummy_class = dummy_class.include Atheneum.upper_case :item
44
+ store = dummy_class.new
45
+ store.item = 'item'
46
+ assert_equal 'item'.upcase, store.send(:upper_cased_item)
47
+ end
48
+
49
+ def test_can_retrieve_a_item_upper_cased
50
+ dummy_class = Struct.new(:upper_cased_item)
51
+ dummy_class = dummy_class.include Atheneum.upper_case :item
52
+ store = dummy_class.new 'item'.upcase
53
+ assert_equal 'item', store.item
54
+ end
55
+
56
+ def test_can_include_multiple_strategies
57
+ dummy_class = Struct.new(:upper_cased_item, :reversed_other)
58
+ dummy_class = dummy_class.include Atheneum.upper_case :item
59
+ dummy_class = dummy_class.include Atheneum.reverse :other
60
+ store = dummy_class.new 'item'.upcase, 'password'.reverse
61
+ assert_equal 'item', store.item
62
+ assert_equal 'password', store.other
63
+ end
64
+
65
+ def test_method_missing_doesnt_affect_host_class
66
+ dummy_class = Struct.new(:reversed_password)
67
+ dummy_class = dummy_class.include Atheneum.reverse :password
68
+ assert_raises NoMethodError do
69
+ dummy_class.blah
70
+ end
71
+ end
72
+
73
+ def test_privatizes_storage_methods
74
+ dummy_class = Struct.new(:reversed_password)
75
+ dummy_class = dummy_class.include Atheneum.reverse :password
76
+ store = dummy_class.new
77
+ assert_raises NoMethodError do
78
+ store.reversed_password
79
+ end
80
+ assert_raises NoMethodError do
81
+ store.reversed_password = 3
82
+ end
83
+ end
84
+
85
+ def test_privatizes_storage_methods_diff
86
+ dummy_class = Struct.new(:upper_cased_item)
87
+ dummy_class = dummy_class.include Atheneum.upper_case :item
88
+ store = dummy_class.new
89
+ assert_raises NoMethodError do
90
+ store.upper_cased_item
91
+ end
92
+ assert_raises NoMethodError do
93
+ store.upper_cased_item = 3
94
+ end
95
+ end
96
+
97
+ def test_doesnt_privatizes_storage_methods_diff_on_option
98
+ dummy_class = Struct.new(:upper_cased_item)
99
+ dummy_class = dummy_class.include Atheneum.upper_case :item, :privatise => false
100
+ store = dummy_class.new
101
+ store.upper_cased_item
102
+ store.upper_cased_item = 3
103
+ end
104
+
105
+ def test_can_overwrite_prefix
106
+ dummy_class = Struct.new(:random_password)
107
+ dummy_class = dummy_class.include Atheneum.reverse :password, :prefix => :random
108
+ store = dummy_class.new
109
+ store.password = 'password'
110
+ assert_equal 'password'.reverse, store.send(:random_password)
111
+ end
112
+ end
@@ -0,0 +1,28 @@
1
+ require 'bcrypt'
2
+ require_relative '../test_config'
3
+
4
+ BCrypt::Engine.cost = 1
5
+
6
+ class BcryptTest < MiniTest::Test
7
+ def strategy(options={})
8
+ @strategy = Atheneum::Strategy::Crypt.new options
9
+ end
10
+
11
+ def teardown
12
+ @strategy = nil
13
+ end
14
+
15
+ def test_hashes_saved_string
16
+ BCrypt::Password.stub :create, 'hashed' do
17
+ assert_equal 'hashed', strategy.pack('string')
18
+ end
19
+ end
20
+
21
+ def test_returns_saved_item
22
+ assert_equal strategy.unpack(BCrypt::Password.create('password').to_s), 'password'
23
+ end
24
+
25
+ def test_stored_attribute_prefixed_with_crypted
26
+ assert_equal 'crypted_password', strategy.store_for(:password)
27
+ end
28
+ end
@@ -0,0 +1,6 @@
1
+ require 'atheneum'
2
+ require 'minitest/autorun'
3
+ require 'minitest/reporters'
4
+
5
+ reporter_options = {color: true, slow_count: 5}
6
+ Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new(reporter_options)]
metadata ADDED
@@ -0,0 +1,141 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: atheneum
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Peter
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 5.4.3
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 5.4.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest-reporters
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.0.6
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.0.6
69
+ - !ruby/object:Gem::Dependency
70
+ name: bcrypt
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 3.1.9
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 3.1.9
83
+ description: "Simply declare attributes that require obscuring and that will make
84
+ it so.\n Useful in exposing buisness logic in objects that
85
+ use BCrypt\n This gem currently assumes that BCrypt is
86
+ available rather than adding it as a dependency,\n future
87
+ versions might support general strategies.\n "
88
+ email:
89
+ - peterhsaxton@gmail.com
90
+ executables: []
91
+ extensions: []
92
+ extra_rdoc_files: []
93
+ files:
94
+ - ".gitignore"
95
+ - Gemfile
96
+ - LICENSE.txt
97
+ - README.md
98
+ - Rakefile
99
+ - atheneum.gemspec
100
+ - lib/atheneum.rb
101
+ - lib/atheneum/errors.rb
102
+ - lib/atheneum/storage.rb
103
+ - lib/atheneum/strategy.rb
104
+ - lib/atheneum/strategy/base.rb
105
+ - lib/atheneum/strategy/crypt.rb
106
+ - lib/atheneum/strategy/reverse.rb
107
+ - lib/atheneum/strategy/upper_case.rb
108
+ - lib/atheneum/version.rb
109
+ - tasks/test.rake
110
+ - test/atheneum/atheneum_test.rb
111
+ - test/strategy/crypt_test.rb
112
+ - test/test_config.rb
113
+ homepage: ''
114
+ licenses:
115
+ - MIT
116
+ metadata: {}
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubyforge_project:
133
+ rubygems_version: 2.2.2
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: A micro gem for the immaculate inclusion of BCrypt protected data for example
137
+ passwords
138
+ test_files:
139
+ - test/atheneum/atheneum_test.rb
140
+ - test/strategy/crypt_test.rb
141
+ - test/test_config.rb