wristband 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.DS_Store +0 -0
  2. data/Gemfile +14 -0
  3. data/Gemfile.lock +88 -0
  4. data/README.md +113 -0
  5. data/Rakefile +21 -0
  6. data/VERSION +1 -0
  7. data/app/controllers/application_controller.rb +10 -0
  8. data/app/controllers/sessions_controller.rb +34 -0
  9. data/app/controllers/users_controller.rb +34 -0
  10. data/app/mailers/user_mailer.rb +33 -0
  11. data/app/models/session_user.rb +59 -0
  12. data/app/models/user.rb +52 -0
  13. data/app/views/layouts/application.html.erb +14 -0
  14. data/app/views/sessions/new.html.haml +15 -0
  15. data/app/views/user_mailer/email_verification.text.html.rhtml +7 -0
  16. data/app/views/user_mailer/email_verification.text.plain.rhtml +9 -0
  17. data/app/views/user_mailer/forgot_password.text.html.rhtml +10 -0
  18. data/app/views/user_mailer/forgot_password.text.plain.rhtml +10 -0
  19. data/app/views/users/show.html.haml +6 -0
  20. data/config/application.rb +15 -0
  21. data/config/boot.rb +13 -0
  22. data/config/database.yml +16 -0
  23. data/config/environment.rb +5 -0
  24. data/config/environments/development.rb +26 -0
  25. data/config/environments/production.rb +49 -0
  26. data/config/environments/test.rb +35 -0
  27. data/config/initializers/wristband.rb +1 -0
  28. data/config/locales/en.yml +5 -0
  29. data/config/routes.rb +11 -0
  30. data/config.ru +4 -0
  31. data/db/migrate/01_create_users_table.rb +26 -0
  32. data/db/schema.rb +27 -0
  33. data/lib/generators/wristband/.DS_Store +0 -0
  34. data/lib/generators/wristband/wristband_generator.rb +56 -0
  35. data/lib/wristband/application_extensions.rb +67 -0
  36. data/lib/wristband/authority_check.rb +160 -0
  37. data/lib/wristband/support.rb +28 -0
  38. data/lib/wristband/user_extensions.rb +89 -0
  39. data/lib/wristband.rb +86 -0
  40. data/public/robots.txt +5 -0
  41. data/script/rails +6 -0
  42. data/test/dummy/user.rb +13 -0
  43. data/test/test_helper.rb +78 -0
  44. data/test/unit/has_authorities_test.rb +86 -0
  45. data/test/unit/session_user_test.rb +8 -0
  46. data/test/unit/user_test.rb +105 -0
  47. data/wristband.gemspec +107 -0
  48. metadata +209 -0
@@ -0,0 +1,35 @@
1
+ Wristband::Application.configure do
2
+ # Settings specified here will take precedence over those in config/application.rb
3
+
4
+ # The test environment is used exclusively to run your application's
5
+ # test suite. You never need to work with it otherwise. Remember that
6
+ # your test database is "scratch space" for the test suite and is wiped
7
+ # and recreated between test runs. Don't rely on the data there!
8
+ config.cache_classes = true
9
+
10
+ # Log error messages when you accidentally call methods on nil.
11
+ config.whiny_nils = true
12
+
13
+ # Show full error reports and disable caching
14
+ config.consider_all_requests_local = true
15
+ config.action_controller.perform_caching = false
16
+
17
+ # Raise exceptions instead of rendering exception templates
18
+ config.action_dispatch.show_exceptions = false
19
+
20
+ # Disable request forgery protection in test environment
21
+ config.action_controller.allow_forgery_protection = false
22
+
23
+ # Tell Action Mailer not to deliver emails to the real world.
24
+ # The :test delivery method accumulates sent emails in the
25
+ # ActionMailer::Base.deliveries array.
26
+ config.action_mailer.delivery_method = :test
27
+
28
+ # Use SQL instead of Active Record's schema dumper when creating the test database.
29
+ # This is necessary if your schema can't be completely dumped by the schema dumper,
30
+ # like if you have constraints or database-specific column types
31
+ # config.active_record.schema_format = :sql
32
+
33
+ # Print deprecation notices to the stderr
34
+ config.active_support.deprecation = :stderr
35
+ end
@@ -0,0 +1 @@
1
+ require 'wristband'
@@ -0,0 +1,5 @@
1
+ # Sample localization file for English. Add more files in this directory for other locales.
2
+ # See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3
+
4
+ en:
5
+ hello: "Hello world"
data/config/routes.rb ADDED
@@ -0,0 +1,11 @@
1
+ Rails::Application.routes.draw do
2
+
3
+ post '/login', :to => 'sessions#create'
4
+ get '/login', :to => 'sessions#new'
5
+ get '/logout', :to => 'sessions#destroy'
6
+ match '/forgot_password', :to => 'sessions#forgot_password'
7
+
8
+ resources :users
9
+ match '/register', :to => 'users#new'
10
+
11
+ end
data/config.ru ADDED
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run Wristband::Application
@@ -0,0 +1,26 @@
1
+ class CreateUsersTable < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :users do |t|
4
+ t.string :email
5
+ t.string :email_validation_key
6
+ t.datetime :validated_at
7
+ t.string :password_crypt, :limit => 40
8
+ t.string :password_salt, :limit => 40
9
+ t.string :remember_token
10
+ t.string :role
11
+ t.timestamps
12
+ # --- Other useful fields ---
13
+ # t.string :first_name
14
+ # t.string :last_name
15
+ # t.string :address
16
+ # t.string :city
17
+ # t.string :state
18
+ # t.string :zip
19
+ # t.string :ip
20
+ end
21
+ end
22
+
23
+ def self.down
24
+ drop_table :users
25
+ end
26
+ end
data/db/schema.rb ADDED
@@ -0,0 +1,27 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # Note that this schema.rb definition is the authoritative source for your
6
+ # database schema. If you need to create the application database on another
7
+ # system, you should be using db:schema:load, not running all the migrations
8
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
10
+ #
11
+ # It's strongly recommended to check this file into your version control system.
12
+
13
+ ActiveRecord::Schema.define(:version => 1) do
14
+
15
+ create_table "users", :force => true do |t|
16
+ t.string "email"
17
+ t.string "email_validation_key"
18
+ t.datetime "validated_at"
19
+ t.string "password_crypt", :limit => 40
20
+ t.string "password_salt", :limit => 40
21
+ t.string "remember_token"
22
+ t.string "role"
23
+ t.datetime "created_at"
24
+ t.datetime "updated_at"
25
+ end
26
+
27
+ end
Binary file
@@ -0,0 +1,56 @@
1
+ class WristbandGenerator < Rails::Generators::Base
2
+ include Rails::Generators::Migration
3
+
4
+ source_root File.expand_path('../../../..', __FILE__)
5
+
6
+ def generate_models
7
+ copy_file 'app/models/user.rb', 'app/models/user.rb'
8
+ copy_file 'app/models/session_user.rb', 'app/models/session_user.rb'
9
+ end
10
+
11
+ def generate_controllers
12
+ copy_file 'app/controllers/users_controller.rb', 'app/controllers/users_controller.rb'
13
+ copy_file 'app/controllers/sessions_controller.rb', 'app/controllers/sessions_controller.rb'
14
+ end
15
+
16
+ def generate_views
17
+ copy_file 'app/views/users/show.html.haml', 'app/views/users/show.html.haml'
18
+ copy_file 'app/views/sessions/new.html.haml', 'app/views/sessions/new.html.haml'
19
+
20
+ end
21
+ def generate_user_mailer
22
+ copy_file 'app/mailers/user_mailer.rb', 'app/mailers/user_mailer.rb'
23
+ copy_file 'app/views/user_mailer/forgot_password.text.html.rhtml', 'app/views/user_mailer/forgot_password.text.html.rhtml'
24
+ copy_file 'app/views/user_mailer/forgot_password.text.plain.rhtml', 'app/views/user_mailer/forgot_password.text.plain.rhtml'
25
+ copy_file 'app/views/user_mailer/email_verification.text.html.rhtml', 'app/views/user_mailer/email_verification.text.html.rhtml'
26
+ copy_file 'app/views/user_mailer/email_verification.text.plain.rhtml', 'app/views/user_mailer/email_verification.text.plain.rhtml'
27
+ end
28
+
29
+ def generate_migration
30
+ destination = File.expand_path('db/migrate/01_create_users_table.rb', self.destination_root)
31
+ migration_dir = File.dirname(destination)
32
+ destination = self.class.migration_exists?(migration_dir, 'create_users_table')
33
+
34
+ if destination
35
+ puts "\e[0m\e[31mFound existing create_users_table.rb migration. Remove it if you want to regenerate.\e[0m"
36
+ else
37
+ migration_template 'db/migrate/01_create_users_table.rb', 'db/migrate/create_users_table.rb'
38
+ end
39
+ end
40
+
41
+ def self.next_migration_number(dirname)
42
+ orm = Rails.configuration.generators.options[:rails][:orm]
43
+ require "rails/generators/#{orm}"
44
+ "#{orm.to_s.camelize}::Generators::Base".constantize.next_migration_number(dirname)
45
+ end
46
+
47
+ # def generate_routes
48
+ # route "get '/login', :to => 'sessions#new'"
49
+ # route "post '/login', :to => 'sessions#create'"
50
+ # route "get '/logout', :to => 'sessions#destroy'"
51
+ # route "match '/forgot_password', :to => 'users#forgot_password'"
52
+ # route "resources :users"
53
+ # route "match '/register', :to => 'users#new'"
54
+ # end
55
+
56
+ end
@@ -0,0 +1,67 @@
1
+ module Wristband
2
+ module ApplicationExtensions
3
+ def self.included(base)
4
+ base.send(:extend, Wristband::ApplicationExtensions::ClassMethods)
5
+ base.send(:include, Wristband::ApplicationExtensions::InstanceMethods)
6
+ base.send(:helper_method, :logged_in?, :current_user) if base.respond_to?(:helper_method)
7
+ end
8
+
9
+ module ClassMethods
10
+ # ...
11
+ end
12
+
13
+ module InstanceMethods
14
+ def login(session_user)
15
+ login_as_user(session_user.user, session_user.remember_me)
16
+ end
17
+
18
+ def login_as_user(user, remember_me=false)
19
+ self.current_user = user
20
+ if remember_me
21
+ token = Support.encrypt_with_salt(user.id.to_s, Time.now.to_f.to_s)
22
+ cookies[:login_token] = { :value => token, :expires => 2.weeks.from_now.utc }
23
+ user.update_attribute(:remember_token, token)
24
+ end
25
+ end
26
+
27
+ # Logs a user out and deletes the remember_token.
28
+ def logout
29
+ current_user.update_attribute(:remember_token, nil) if current_user
30
+ cookies.delete(:login_token)
31
+ reset_session
32
+ end
33
+
34
+ # Returns true if a user is logged in
35
+ def logged_in?
36
+ !!current_user
37
+ end
38
+
39
+ # Returns the current user in session. Use this on your views and controllers.
40
+ def current_user
41
+ @current_user ||= (session[:user_id] and ::User.find_by_id(session[:user_id]))
42
+ end
43
+
44
+ # Sets the current user in session
45
+ def current_user=(user)
46
+ @current_user = user
47
+ session[:user_id] = (user and user.id)
48
+ end
49
+
50
+ # Logs a user automatically from his cookie
51
+ #
52
+ # You can use this function as a before filter on your controllers.
53
+ def login_from_cookie
54
+ return if (logged_in? or !cookies[:login_token])
55
+ self.current_user = ::User.find_by_remember_token(cookies[:login_token])
56
+ end
57
+
58
+ # You can use this function as a before filter on your controllers that require autentication.
59
+ #
60
+ # If the user is not logged in +respond_not_logged_in+ will be called.
61
+ def login_required
62
+ logged_in?
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,160 @@
1
+ # = AuthorityCheck
2
+ # The different user authorities are defined in a separate class so as to reduce
3
+ # clutter in the User model itself.
4
+ #
5
+ # class User < ActiveRecord::Base
6
+ # wristband :has_authorities => true
7
+ # end
8
+ #
9
+ # This will refer to the class UserAuthorityCheck for all authority tests, but the
10
+ # name of this module can be defined as required:
11
+ #
12
+ # class User < ActiveRecord::Base
13
+ # has_authorities => :permissions
14
+ # end
15
+ #
16
+ # That would reference the class UserPermissions instead for all tests.
17
+ #
18
+ # A sample authority checking class is defined as:
19
+ #
20
+ # class UserAuthorityCheck < AuthorityCheck
21
+ # def wear_shoes?
22
+ # unless (@user.name.match(/^a/i))
23
+ # fail!("Only people with names that start with 'A' can wear shoes.")
24
+ # end
25
+ # end
26
+ # end
27
+ #
28
+ # <b>Note the syntax: </b>All authority checks are defined as ending with a trailing question mark
29
+ # character.
30
+ #
31
+ # A check is considered to have passed if
32
+ # * a call to <tt>allow!</tt> has been made, or
33
+ # * no calls to <tt>fail!</tt> have been made.
34
+ #
35
+ # Once defined, the user authorities are checked via a call to a User instance:
36
+ #
37
+ # user.has_authority_to?(:wear_shoes)
38
+ #
39
+ # While the <tt>has_authority_to?</tt> method returns only true or false, a call to
40
+ # <tt>has_objections_to?</tt> will return nil on success or any error messages if there
41
+ # is a failure.
42
+ #
43
+ #
44
+ # ==== Passing parameters to the authority methods
45
+ #
46
+ # Any call to these tests may include options in the form of a Hash:
47
+ #
48
+ # user.has_authority_to?(:send_message, :text => "Foo bar")
49
+ #
50
+ # These options can be acted upon within the authority check:
51
+ #
52
+ # def send_message?
53
+ # if (options[:text].match(/foo/i))
54
+ # fail!("Messages may not contain forbidden words.")
55
+ # end
56
+ # end
57
+ #
58
+ # ==== Before chains
59
+ #
60
+ # In addition to defining straight tests, a chain can be defined to run before
61
+ # any of the tests themselves. This allows certain calls to be over-ruled. For
62
+ # example:
63
+ #
64
+ # before_check :allow_if_admin!
65
+ #
66
+ # def allow_if_admin!
67
+ # if (@user.is_admin?)
68
+ # allow!
69
+ # end
70
+ # end
71
+ #
72
+ # In this case, the <tt>allow_if_admin!</tt> method will be called before any checks are performed. If
73
+ # the <tt>allow!</tt> method is executed, all subsequent tests are halted and the check
74
+ # is considered to have passed.
75
+
76
+ class AuthorityCheck
77
+ attr_accessor :user
78
+ attr_accessor :options
79
+
80
+ def initialize(user, test_method, options = { })
81
+ self.user = user
82
+ self.options = options
83
+
84
+ @test_method = "#{test_method}?".to_sym
85
+
86
+ @result = nil
87
+ end
88
+
89
+ # Checkes if the user is allowed to do something.
90
+ # Returns <tt>true</tt> or <tt>false</tt>
91
+ def allowed_to?
92
+ execute_tests!
93
+
94
+ # Either explicitly allowed (true) or not given any reasons as to why
95
+ # not (nil, empty)
96
+ (@result === true or (@result === nil and @reasons.blank?)) ? true : false
97
+ end
98
+
99
+ def denied_for_reasons
100
+ @reasons = [ ]
101
+
102
+ allowed_to? ? nil : @reasons
103
+ end
104
+
105
+
106
+ class << self
107
+ def check_chain
108
+ @check_chain ||= [ ]
109
+ end
110
+
111
+ def check_chain=(value)
112
+ @check_chain = value
113
+ end
114
+
115
+ def before_check(method, options = { })
116
+ self.check_chain += remap_chain_methods([ method ])
117
+ end
118
+
119
+ def check_alias_as(original, *aliases)
120
+ aliases.flatten.each do |alias_name|
121
+ alias_method alias_name, original
122
+ end
123
+ end
124
+ end
125
+
126
+
127
+
128
+ protected
129
+ def allow!
130
+ @result = true
131
+ end
132
+
133
+ def fail!(message)
134
+ if (@reasons and message)
135
+ @reasons << message
136
+ end
137
+
138
+ @result = false
139
+ end
140
+
141
+ def execute_tests!
142
+ self.class.check_chain.each do |method|
143
+ case (method)
144
+ when Symbol, String
145
+ send(method)
146
+ else
147
+ method.call
148
+ end
149
+
150
+ # Stop evaluating if this test called allow!
151
+ return if (@result === true)
152
+ end
153
+
154
+ self.send(@test_method)
155
+ end
156
+
157
+ def self.remap_chain_methods(methods)
158
+ methods
159
+ end
160
+ end
@@ -0,0 +1,28 @@
1
+ module Wristband
2
+ module Support
3
+ CONSONANTS = %w( b c d f g h j k l m n p qu r s t v w x z ch cr fr nd ng nk nt ph pr rd sh sl sp st th tr )
4
+ VOWELS = %w( a e i o u y )
5
+
6
+ def random_string(length = 8)
7
+ (1 .. length).collect { |n|
8
+ (n % 2 != 0) ? CONSONANTS[rand(CONSONANTS.size)] : VOWELS[rand(VOWELS.size)]
9
+ }.to_s[0, length]
10
+ end
11
+ module_function :random_string
12
+
13
+ def encrypt_with_salt(password, salt)
14
+ return password unless (salt and !salt.empty?)
15
+
16
+ Digest::SHA1.hexdigest([ password, salt ].to_s)
17
+ end
18
+ module_function :encrypt_with_salt
19
+
20
+ def random_salt(length = nil)
21
+ salt = Digest::SHA1.hexdigest([ rand, rand, random_string(64), rand, rand ].to_s)
22
+
23
+ length ? salt[0, length] : salt
24
+ end
25
+ module_function :random_salt
26
+
27
+ end
28
+ end
@@ -0,0 +1,89 @@
1
+ module Wristband
2
+ module UserExtensions
3
+ def self.included(base)
4
+ base.send(:extend, Wristband::UserExtensions::ClassMethods)
5
+ base.send(:include, Wristband::UserExtensions::InstanceMethods)
6
+ base.send(:extend, Wristband::Support)
7
+ end
8
+
9
+ module ClassMethods
10
+ def authenticate(email, password)
11
+ self.execute_authentication_chain(self, self.wristband[:before_authentication_chain]) == false and return
12
+ user = nil
13
+ wristband[:login_with_fields].find do |field|
14
+ user = send("find_by_#{field}", email)
15
+ end
16
+ (user and user.password_match?(password)) || return
17
+ self.execute_authentication_chain(user, self.wristband[:after_authentication_chain]) == false and return
18
+ user
19
+ end
20
+
21
+ def execute_authentication_chain(object, list)
22
+ list.each do |func|
23
+ case func
24
+ when Symbol,String
25
+ object.send(func) == false and return false
26
+ when Proc
27
+ func.call(object) == false and return false
28
+ end
29
+ end
30
+ end
31
+
32
+ def verify_email!(email_validation_key)
33
+ if user = find_by_email_validation_key(email_validation_key)
34
+ user.update_attribute(:validated_at, Time.now.to_s(:db))
35
+ user
36
+ else
37
+ raise UserVerificationError, 'We were not able to verify your account or it may have been verified already. Please contact us for assistance.'.t
38
+ end
39
+ end
40
+
41
+ def roles_for_select
42
+ self.class.wristband[:roles].collect{ |k| [ k.to_s.titleize, k.to_s] }
43
+ end
44
+
45
+ end
46
+
47
+ module InstanceMethods
48
+
49
+ def has_authority_to?(action, options = { })
50
+ self.class.wristband[:authority_class].new(self, action, options).allowed_to?
51
+ end
52
+
53
+ def has_objections_to?(action, options = { })
54
+ self.class.wristband[:authority_class].new(self, action, options).denied_for_reasons
55
+ end
56
+
57
+ def initialize_salt
58
+ self.password_salt = Wristband::Support.random_salt
59
+ end
60
+
61
+ def initialize_token
62
+ self.remember_token = Wristband::Support.random_salt(16)
63
+ end
64
+
65
+ def encrypt_password
66
+ initialize_salt if new_record?
67
+ return if self.password.blank?
68
+ self.send("#{self.class.wristband[:password_column]}=", Wristband::Support.encrypt_with_salt(self.password, self.password_salt))
69
+ end
70
+
71
+ def password_match?(string)
72
+ self.send(self.class.wristband[:password_column]) == Wristband::Support.encrypt_with_salt(string, self.password_salt)
73
+ end
74
+
75
+ def password_crypted?
76
+ self.password_salt and !self.password_salt.empty?
77
+ end
78
+
79
+ def password_crypt=(value)
80
+ if (value != read_attribute(:password_crypt))
81
+ initialize_token
82
+ end
83
+
84
+ write_attribute(:password_crypt, value)
85
+ end
86
+
87
+ end
88
+ end
89
+ end
data/lib/wristband.rb ADDED
@@ -0,0 +1,86 @@
1
+ require 'wristband/user_extensions'
2
+ require 'wristband/support'
3
+ require 'wristband/application_extensions'
4
+ require 'wristband/authority_check'
5
+
6
+ module Wristband
7
+
8
+ VERSION = "1.0.0"
9
+
10
+ class Engine < ::Rails::Engine; end
11
+
12
+ class << self
13
+ def included base #:nodoc:
14
+ base.extend ClassMethods
15
+ end
16
+ end
17
+
18
+ module ClassMethods
19
+ def wristband(options={})
20
+ options[:login_with] ||= [:email]
21
+ options[:before_authentication] ||= []
22
+ options[:after_authentication] ||= []
23
+ options[:has_authorities] ||= false
24
+ options[:roles] ||= []
25
+
26
+ class_eval do
27
+ include Wristband::UserExtensions
28
+
29
+ options[:password_column] ||= :password_crypt
30
+
31
+ # These two are used on the login form
32
+ attr_accessor :password
33
+ attr_accessor :password_confirmation
34
+
35
+ before_save :encrypt_password
36
+
37
+ # Add roles
38
+ unless options[:roles].blank?
39
+ options[:roles].each do |role|
40
+ define_method "is_#{role}?" do
41
+ self.role.to_s == role.to_s
42
+ end
43
+ end
44
+ end
45
+
46
+ class << self
47
+ attr_accessor :wristband
48
+ end
49
+ end
50
+
51
+ self.wristband = {
52
+ :login_with_fields => [options[:login_with]].flatten,
53
+ :before_authentication_chain => [options[:before_authentication]].flatten,
54
+ :after_authentication_chain => [options[:after_authentication]].flatten,
55
+ :password_column => options[:password_column],
56
+ :roles => options[:roles]
57
+ }
58
+
59
+ if options[:has_authorities]
60
+ self.wristband[:authority_class] = UtilityMethods.interpret_class_specification(self, options[:has_authorities])
61
+ end
62
+ end
63
+ end
64
+
65
+ module UtilityMethods
66
+ def self.interpret_class_specification(model_class, with_class)
67
+ case (with_class)
68
+ when Symbol
69
+ "#{model_class.class_name}#{with_class.to_s.camelcase}".constantize
70
+ when String
71
+ with_class.constantize
72
+ when true
73
+ "#{model_class.name}AuthorityCheck".constantize
74
+ else
75
+ with_class
76
+ end
77
+ end
78
+ end
79
+
80
+ end
81
+
82
+
83
+ ActiveRecord::Base.send(:extend, Wristband::ClassMethods)
84
+ ActionController::Base.send(:include, Wristband::ApplicationExtensions)
85
+
86
+ class UserVerificationError < StandardError; end
data/public/robots.txt ADDED
@@ -0,0 +1,5 @@
1
+ # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2
+ #
3
+ # To ban all spiders from the entire site uncomment the next two lines:
4
+ # User-Agent: *
5
+ # Disallow: /
data/script/rails ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,13 @@
1
+ TestDummy.declare(User) do
2
+ dummy :email do
3
+ Faker::Internet.email
4
+ end
5
+
6
+ dummy :password do
7
+ 'passpass'
8
+ end
9
+
10
+ dummy :role do
11
+ User::ROLES[0]
12
+ end
13
+ end