apispree_auth 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/LICENSE +26 -0
  2. data/README.md +36 -0
  3. data/app/controllers/admin_controller_decorator.rb +7 -0
  4. data/app/controllers/admin_orders_controller_decorator.rb +15 -0
  5. data/app/controllers/admin_resource_controller_decorator.rb +3 -0
  6. data/app/controllers/checkout_controller_decorator.rb +42 -0
  7. data/app/controllers/orders_controller_decorator.rb +17 -0
  8. data/app/controllers/resource_controller_decorator.rb +25 -0
  9. data/app/controllers/spree/base_controller_decorator.rb +49 -0
  10. data/app/controllers/user_passwords_controller.rb +20 -0
  11. data/app/controllers/user_registrations_controller.rb +64 -0
  12. data/app/controllers/user_sessions_controller.rb +81 -0
  13. data/app/controllers/users_controller.rb +54 -0
  14. data/app/helpers/users_helper.rb +13 -0
  15. data/app/models/ability.rb +64 -0
  16. data/app/models/order_decorator.rb +12 -0
  17. data/app/models/spree_auth_configuration.rb +4 -0
  18. data/app/models/spree_current_order_decorator.rb +14 -0
  19. data/app/models/tokenized_permission.rb +3 -0
  20. data/app/models/user.rb +85 -0
  21. data/app/models/user_mailer.rb +13 -0
  22. data/app/views/checkout/registration.html.erb +20 -0
  23. data/app/views/layouts/admin/_login_nav.html.erb +8 -0
  24. data/app/views/shared/_flashes.html.erb +9 -0
  25. data/app/views/shared/_login.html.erb +20 -0
  26. data/app/views/shared/_login_bar.html.erb +6 -0
  27. data/app/views/shared/_user_form.html.erb +17 -0
  28. data/app/views/shared/unauthorized.html.erb +0 -0
  29. data/app/views/user_mailer/reset_password_instructions.text.erb +10 -0
  30. data/app/views/user_passwords/edit.html.erb +15 -0
  31. data/app/views/user_passwords/new.html.erb +13 -0
  32. data/app/views/user_registrations/new.html.erb +23 -0
  33. data/app/views/user_sessions/authorization_failure.html.erb +4 -0
  34. data/app/views/user_sessions/new.html.erb +13 -0
  35. data/app/views/users/edit.html.erb +11 -0
  36. data/app/views/users/show.html.erb +50 -0
  37. data/config/cucumber.yml +10 -0
  38. data/config/initializers/devise.rb +136 -0
  39. data/config/locales/en.yml +46 -0
  40. data/config/routes.rb +28 -0
  41. data/db/migrate/20101026184950_rename_columns_for_devise.rb +39 -0
  42. data/db/migrate/20101214150824_convert_user_remember_field.rb +11 -0
  43. data/db/migrate/20101217012656_create_tokenized_permissions.rb +18 -0
  44. data/db/migrate/20101219201531_tokens_for_legacy_orders.rb +12 -0
  45. data/db/sample/users.rb +53 -0
  46. data/lib/apispree_auth.rb +29 -0
  47. data/lib/spree/auth/config.rb +22 -0
  48. data/lib/spree/token_resource.rb +23 -0
  49. data/lib/spree_auth_hooks.rb +6 -0
  50. data/lib/tasks/auth.rake +8 -0
  51. data/lib/tasks/install.rake +23 -0
  52. metadata +129 -0
@@ -0,0 +1,10 @@
1
+ <%
2
+ rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
3
+ rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
4
+ std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} --strict --tags ~@wip"
5
+ ci_opts = "--format progress --strict"
6
+ %>
7
+ default: <%= std_opts %> features
8
+ wip: --tags @wip:3 --wip features
9
+ ci: <%= ci_opts %> features CI=true
10
+ rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip
@@ -0,0 +1,136 @@
1
+ # Use this hook to configure devise mailer, warden hooks and so forth. The first
2
+ # four configuration values can also be set straight in your models.
3
+ Devise.setup do |config|
4
+ # ==> Mailer Configuration
5
+ # Configure the e-mail address which will be shown in DeviseMailer.
6
+ config.mailer_sender = "please-change-me@config-initializers-devise.com"
7
+
8
+ # Configure the class responsible to send e-mails.
9
+ config.mailer = "UserMailer"
10
+
11
+ # ==> ORM configuration
12
+ # Load and configure the ORM. Supports :active_record (default) and
13
+ # :mongoid (bson_ext recommended) by default. Other ORMs may be
14
+ # available as additional gems.
15
+ require 'devise/orm/active_record'
16
+
17
+ # ==> Configuration for any authentication mechanism
18
+ # Configure which keys are used when authenticating an user. By default is
19
+ # just :email. You can configure it to use [:username, :subdomain], so for
20
+ # authenticating an user, both parameters are required. Remember that those
21
+ # parameters are used only when authenticating and not when retrieving from
22
+ # session. If you need permissions, you should implement that in a before filter.
23
+ # config.authentication_keys = [ :email ]
24
+
25
+ # Tell if authentication through request.params is enabled. True by default.
26
+ # config.params_authenticatable = true
27
+
28
+ # Tell if authentication through HTTP Basic Auth is enabled. False by default.
29
+ config.http_authenticatable = true
30
+
31
+ # Set this to true to use Basic Auth for AJAX requests. True by default.
32
+ #config.http_authenticatable_on_xhr = false
33
+
34
+ # The realm used in Http Basic Authentication
35
+ config.http_authentication_realm = "Spree Application"
36
+
37
+ # ==> Configuration for :database_authenticatable
38
+ # For bcrypt, this is the cost for hashing the password and defaults to 10. If
39
+ # using other encryptors, it sets how many times you want the password re-encrypted.
40
+ config.stretches = 20
41
+
42
+ # Setup a pepper to generate the encrypted password.
43
+ config.pepper = "0bfa9e2cb4a5efd0d976518a3d82e345060547913d2fd1dd2f32b0c8dbbbb5d3dc20b86d0fed31aca9513bccdf51643700ea277d9c64d9ce8ef886bf39293453"
44
+
45
+ # ==> Configuration for :confirmable
46
+ # The time you want to give your user to confirm his account. During this time
47
+ # he will be able to access your application without confirming. Default is nil.
48
+ # When confirm_within is zero, the user won't be able to sign in without confirming.
49
+ # You can use this to let your user access some features of your application
50
+ # without confirming the account, but blocking it after a certain period
51
+ # (ie 2 days).
52
+ # config.confirm_within = 2.days
53
+
54
+ # ==> Configuration for :rememberable
55
+ # The time the user will be remembered without asking for credentials again.
56
+ # config.remember_for = 2.weeks
57
+
58
+ # If true, a valid remember token can be re-used between multiple browsers.
59
+ # config.remember_across_browsers = true
60
+
61
+ # If true, extends the user's remember period when remembered via cookie.
62
+ # config.extend_remember_period = false
63
+
64
+ # ==> Configuration for :validatable
65
+ # Range for password length
66
+ # config.password_length = 6..20
67
+
68
+ # Regex to use to validate the email address
69
+ config.email_regexp = /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i
70
+
71
+ # ==> Configuration for :timeoutable
72
+ # The time you want to timeout the user session without activity. After this
73
+ # time the user will be asked for credentials again.
74
+ # config.timeout_in = 10.minutes
75
+
76
+ # ==> Configuration for :lockable
77
+ # Defines which strategy will be used to lock an account.
78
+ # :failed_attempts = Locks an account after a number of failed attempts to sign in.
79
+ # :none = No lock strategy. You should handle locking by yourself.
80
+ # config.lock_strategy = :failed_attempts
81
+
82
+ # Defines which strategy will be used to unlock an account.
83
+ # :email = Sends an unlock link to the user email
84
+ # :time = Re-enables login after a certain amount of time (see :unlock_in below)
85
+ # :both = Enables both strategies
86
+ # :none = No unlock strategy. You should handle unlocking by yourself.
87
+ # config.unlock_strategy = :both
88
+
89
+ # Number of authentication tries before locking an account if lock_strategy
90
+ # is failed attempts.
91
+ # config.maximum_attempts = 20
92
+
93
+ # Time interval to unlock the account if :time is enabled as unlock_strategy.
94
+ # config.unlock_in = 1.hour
95
+
96
+ # ==> Configuration for :token_authenticatable
97
+ # Defines name of the authentication token params key
98
+ config.token_authentication_key = :auth_token
99
+
100
+ # ==> Scopes configuration
101
+ # Turn scoped views on. Before rendering "sessions/new", it will first check for
102
+ # "users/sessions/new". It's turned off by default because it's slower if you
103
+ # are using only default views.
104
+ # config.scoped_views = true
105
+
106
+ # Configure the default scope given to Warden. By default it's the first
107
+ # devise role declared in your routes.
108
+ # config.default_scope = :user
109
+
110
+ # Configure sign_out behavior.
111
+ # By default sign_out is scoped (i.e. /users/sign_out affects only :user scope).
112
+ # In case of sign_out_all_scopes set to true any logout action will sign out all active scopes.
113
+ # config.sign_out_all_scopes = false
114
+
115
+ # ==> Navigation configuration
116
+ # Lists the formats that should be treated as navigational. Formats like
117
+ # :html, should redirect to the sign in page when the user does not have
118
+ # access, but formats like :xml or :json, should return 401.
119
+ # If you have any extra navigational formats, like :iphone or :mobile, you
120
+ # should add them to the navigational formats lists. Default is [:html]
121
+ config.navigational_formats = [:html, :json, :xml]
122
+
123
+ # ==> Warden configuration
124
+ # If you want to use other strategies, that are not (yet) supported by Devise,
125
+ # you can configure them inside the config.warden block. The example below
126
+ # allows you to setup OAuth, using http://github.com/roman/warden_oauth
127
+ #
128
+ # config.warden do |manager|
129
+ # manager.oauth(:twitter) do |twitter|
130
+ # twitter.consumer_secret = <YOUR CONSUMER SECRET>
131
+ # twitter.consumer_key = <YOUR CONSUMER KEY>
132
+ # twitter.options :site => 'http://twitter.com'
133
+ # end
134
+ # manager.default_strategies(:scope => :user).unshift :twitter_oauth
135
+ # end
136
+ end
@@ -0,0 +1,46 @@
1
+ en:
2
+ errors:
3
+ messages:
4
+ not_found: "not found"
5
+ already_confirmed: "was already confirmed"
6
+ not_locked: "was not locked"
7
+ not_saved:
8
+ one: "1 error prohibited this %{resource} from being saved:"
9
+ other: "%{count} errors prohibited this %{resource} from being saved:"
10
+ devise:
11
+ failure:
12
+ unauthenticated: 'You need to sign in or sign up before continuing.'
13
+ unconfirmed: 'You have to confirm your account before continuing.'
14
+ locked: 'Your account is locked.'
15
+ invalid: 'Invalid email or password.'
16
+ invalid_token: 'Invalid authentication token.'
17
+ timeout: 'Your session expired, please sign in again to continue.'
18
+ inactive: 'Your account was not activated yet.'
19
+ user_passwords:
20
+ user:
21
+ send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
22
+ updated: 'Your password was changed successfully. You are now signed in.'
23
+ confirmations:
24
+ send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
25
+ confirmed: 'Your account was successfully confirmed. You are now signed in.'
26
+ user_registrations:
27
+ signed_up: 'Welcome! You have signed up successfully.'
28
+ inactive_signed_up: 'You have signed up successfully. However, we could not sign you in because your account is %{reason}.'
29
+ updated: 'You updated your account successfully.'
30
+ destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
31
+ user_sessions:
32
+ signed_in: 'Signed in successfully.'
33
+ signed_out: 'Signed out successfully.'
34
+ unlocks:
35
+ send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
36
+ unlocked: 'Your account was successfully unlocked. You are now signed in.'
37
+ oauth_callbacks:
38
+ success: 'Successfully authorized from %{kind} account.'
39
+ failure: 'Could not authorize you from %{kind} because "%{reason}".'
40
+ mailer:
41
+ confirmation_instructions:
42
+ subject: 'Confirmation instructions'
43
+ reset_password_instructions:
44
+ subject: 'Reset password instructions'
45
+ unlock_instructions:
46
+ subject: 'Unlock Instructions'
@@ -0,0 +1,28 @@
1
+ Rails.application.routes.draw do
2
+ devise_for :user,
3
+ :controllers => { :sessions => 'user_sessions',
4
+ :registrations => 'user_registrations',
5
+ :passwords => "user_passwords" },
6
+ :skip => [:unlocks, :omniauth_callbacks],
7
+ :path_names => { :sign_out => 'logout'}
8
+ resources :users, :only => [:edit, :update]
9
+
10
+ devise_scope :user do
11
+ get "/login" => "user_sessions#new", :as => :login
12
+ get "/signup" => "user_registrations#new", :as => :signup
13
+ end
14
+
15
+
16
+ match '/checkout/registration' => 'checkout#registration', :via => :get, :as => :checkout_registration
17
+ match '/checkout/registration' => 'checkout#update_registration', :via => :put, :as => :update_checkout_registration
18
+
19
+ match '/orders/:id/token/:token' => 'orders#show', :via => :get, :as => :token_order
20
+
21
+ resource :session do
22
+ member do
23
+ get :nav_bar
24
+ end
25
+ end
26
+ resource :account, :controller => "users"
27
+
28
+ end
@@ -0,0 +1,39 @@
1
+ class RenameColumnsForDevise < ActiveRecord::Migration
2
+ def self.up
3
+ return if column_exists?(:users, :password_salt)
4
+ rename_column :users, :crypted_password, :encrypted_password
5
+ rename_column :users, :salt, :password_salt
6
+ rename_column :users, :remember_token_expires_at, :remember_created_at
7
+ rename_column :users, :login_count, :sign_in_count
8
+ rename_column :users, :failed_login_count, :failed_attempts
9
+ rename_column :users, :single_access_token, :reset_password_token
10
+ rename_column :users, :current_login_at, :current_sign_in_at
11
+ rename_column :users, :last_login_at, :last_sign_in_at
12
+ rename_column :users, :current_login_ip, :current_sign_in_ip
13
+ rename_column :users, :last_login_ip, :last_sign_in_ip
14
+ add_column :users, :authentication_token, :string
15
+ add_column :users, :unlock_token, :string
16
+ add_column :users, :locked_at, :datetime
17
+ remove_column :users, :api_key rescue Exception
18
+ remove_column :users, :openid_identifier
19
+ end
20
+
21
+ def self.down
22
+ remove_column :users, :authentication_token
23
+ remove_column :users, :locked_at
24
+ remove_column :users, :unlock_token
25
+ rename_column :table_name, :new_column_name, :column_name
26
+ rename_column :users, :last_sign_in_ip, :last_login_ip
27
+ rename_column :users, :current_sign_in_ip, :current_login_ip
28
+ rename_column :users, :last_sign_in_at, :last_login_at
29
+ rename_column :users, :current_sign_in_at, :current_login_at
30
+ rename_column :users, :reset_password_token, :single_access_token
31
+ rename_column :users, :failed_attempts, :failed_login_count
32
+ rename_column :users, :sign_in_count, :login_count
33
+ rename_column :users, :remember_created_at, :remember_token_expires_at
34
+ rename_column :users, :password_salt, :salt
35
+ rename_column :users, :encrypted_password, :crypted_password
36
+ add_column :users, :unlock_token, :string
37
+ add_column :users, :openid_identifier, :string
38
+ end
39
+ end
@@ -0,0 +1,11 @@
1
+ class ConvertUserRememberField < ActiveRecord::Migration
2
+ def self.up
3
+ remove_column :users, :remember_created_at
4
+ add_column :users, :remember_created_at, :datetime
5
+ end
6
+
7
+ def self.down
8
+ remove_column :users, :remember_created_at
9
+ add_column :users, :remember_created_at, :string
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ class CreateTokenizedPermissions < ActiveRecord::Migration
2
+
3
+ def self.up
4
+
5
+ create_table :tokenized_permissions do |t|
6
+ t.integer :permissable_id
7
+ t.string :permissable_type
8
+ t.string :token
9
+ t.timestamps
10
+ end
11
+
12
+ add_index "tokenized_permissions", ["permissable_id", "permissable_type"], :name => "index_tokenized_name_and_type"
13
+ end
14
+
15
+ def self.down
16
+ drop_table :tokenized_permissions
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ class TokensForLegacyOrders < ActiveRecord::Migration
2
+ def self.up
3
+ # add token permissions for legacy orders (stop relying on user persistence token)
4
+ Order.all.each do |order|
5
+ next unless order.user
6
+ order.create_tokenized_permission(:token => order.user.persistence_token)
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ end
12
+ end
@@ -0,0 +1,53 @@
1
+ # see last line where we create an admin if there is none, asking for email and password
2
+ def prompt_for_admin_password
3
+ password = ask('Password [spree123]: ', String) do |q|
4
+ q.echo = false
5
+ q.validate = /^(|.{5,40})$/
6
+ q.responses[:not_valid] = "Invalid password. Must be at least 5 characters long."
7
+ q.whitespace = :strip
8
+ end
9
+ password = "spree123" if password.blank?
10
+ password
11
+ end
12
+
13
+ def prompt_for_admin_email
14
+ email = ask('Email [spree@example.com]: ', String) do |q|
15
+ q.echo = true
16
+ q.whitespace = :strip
17
+ end
18
+ email = "spree@example.com" if email.blank?
19
+ email
20
+ end
21
+
22
+ def create_admin_user
23
+ if ENV['AUTO_ACCEPT']
24
+ password = "spree123"
25
+ email = "spree@example.com"
26
+ else
27
+ require 'highline/import'
28
+ puts "Create the admin user (press enter for defaults)."
29
+ #name = prompt_for_admin_name unless name
30
+ email = prompt_for_admin_email
31
+ password = prompt_for_admin_password
32
+ end
33
+ attributes = {
34
+ :password => password,
35
+ :password_confirmation => password,
36
+ :email => email,
37
+ :login => email
38
+ }
39
+
40
+ load 'user.rb'
41
+
42
+ if User.find_by_email(email)
43
+ say "\nWARNING: There is already a user with the email: #{email}, so no account changes were made. If you wish to create an additional admin user, please run rake db:admin:create again with a different email.\n\n"
44
+ else
45
+ admin = User.create(attributes)
46
+ # create an admin role and and assign the admin user to that role
47
+ role = Role.find_or_create_by_name "admin"
48
+ admin.roles << role
49
+ admin.save
50
+ end
51
+ end
52
+
53
+ create_admin_user if User.where("roles.name" => 'admin').includes(:roles).empty?
@@ -0,0 +1,29 @@
1
+ require 'apispree_core'
2
+ require 'devise'
3
+ require 'cancan'
4
+
5
+ require 'spree/auth/config'
6
+ require 'spree/token_resource'
7
+ require 'spree_auth_hooks'
8
+
9
+ module SpreeAuth
10
+ class Engine < Rails::Engine
11
+ def self.activate
12
+ Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator*.rb")) do |c|
13
+ Rails.env.production? ? require(c) : load(c)
14
+ end
15
+
16
+ # monkey patch until new version of devise comes out
17
+ # https://github.com/plataformatec/devise/commit/ec5bfe9119d0e1e633629793b0de1f58f89622dc
18
+ Devise::IndifferentHash.class_eval do
19
+ def [](key)
20
+ super(convert_key(key))
21
+ end
22
+ def to_hash; Hash.new.update(self) end
23
+ end
24
+ end
25
+
26
+ config.to_prepare &method(:activate).to_proc
27
+ ActiveRecord::Base.class_eval { include Spree::TokenResource }
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ module Spree
2
+ module Auth
3
+ # Singleton class to access the shipping configuration object (ActiveShippingConfiguration.first by default) and it's preferences.
4
+ #
5
+ # Usage:
6
+ # Spree::Auth::Config[:foo] # Returns the foo preference
7
+ # Spree::Auth::Config[] # Returns a Hash with all the tax preferences
8
+ # Spree::Auth::Config.instance # Returns the configuration object (AuthConfiguration.first)
9
+ # Spree::Auth::Config.set(preferences_hash) # Set the spree auth preferences as especified in +preference_hash+
10
+ class Config
11
+ include Singleton
12
+ include Spree::PreferenceAccess
13
+
14
+ class << self
15
+ def instance
16
+ return nil unless ActiveRecord::Base.connection.tables.include?('configurations')
17
+ SpreeAuthConfiguration.find_or_create_by_name("Default spree_auth configuration")
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ module Spree::TokenResource
2
+
3
+ module ClassMethods
4
+ def token_resource
5
+ has_one :tokenized_permission, :as => :permissable
6
+ delegate :token, :to => :tokenized_permission, :allow_nil => true
7
+ after_create :create_token
8
+ end
9
+ end
10
+
11
+ module InstanceMethods
12
+ def create_token
13
+ create_tokenized_permission(:token => ActiveSupport::SecureRandom::hex(8))
14
+ token
15
+ end
16
+ end
17
+
18
+ def self.included(receiver)
19
+ receiver.extend ClassMethods
20
+ receiver.send :include, InstanceMethods
21
+ end
22
+
23
+ end
@@ -0,0 +1,6 @@
1
+ class SpreeAuthHooks < Spree::ThemeSupport::HookListener
2
+
3
+ replace :admin_login_navigation_bar, :partial => "layouts/admin/login_nav"
4
+ replace :shared_login_bar, :partial => "shared/login_bar"
5
+
6
+ end