apispree_auth 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,13 @@
1
+ module UsersHelper
2
+ def password_style(user)
3
+ ActiveSupport::Deprecation.warn "[SPREE] Password style has be depreciated due to the removal of OpenID from the Auth Gem. "
4
+ "Please install the spree_social gem to regain this functionality and more."
5
+ ""
6
+ end
7
+ def openid_style(user)
8
+ ActiveSupport::Deprecation.warn "[SPREE] Password style has be depreciated due to the removal of OpenID from the Auth Gem. "
9
+ "Please install the spree_social gem to regain this functionality and more."
10
+ "display:none"
11
+ end
12
+
13
+ end
@@ -0,0 +1,64 @@
1
+ # Implementation class for Cancan gem. Instead of overriding this class, consider adding new permissions
2
+ # using the special +register_ability+ method which allows extensions to add their own abilities.
3
+ #
4
+ # See http://github.com/ryanb/cancan for more details on cancan.
5
+ class Ability
6
+ include CanCan::Ability
7
+
8
+ class_attribute :abilities
9
+ self.abilities = Set.new
10
+
11
+ # Allows us to go beyond the standard cancan initialize method which makes it difficult for engines to
12
+ # modify the default +Ability+ of an application. The +ability+ argument must be a class that includes
13
+ # the +CanCan::Ability+ module. The registered ability should behave properly as a stand-alone class
14
+ # and therefore should be easy to test in isolation.
15
+ def self.register_ability(ability)
16
+ self.abilities.add(ability)
17
+ end
18
+
19
+ def initialize(user)
20
+ self.clear_aliased_actions
21
+
22
+ # override cancan default aliasing (we don't want to differentiate between read and index)
23
+ alias_action :edit, :to => :update
24
+ alias_action :new, :to => :create
25
+ alias_action :new_action, :to => :create
26
+ alias_action :show, :to => :read
27
+
28
+ user ||= User.new
29
+ if user.has_role? 'admin'
30
+ can :manage, :all
31
+ else
32
+ #############################
33
+ can :read, User do |resource|
34
+ resource == user
35
+ end
36
+ can :update, User do |resource|
37
+ resource == user
38
+ end
39
+ can :create, User
40
+ #############################
41
+ can :read, Order do |order, token|
42
+ order.user == user || order.token && token == order.token
43
+ end
44
+ can :update, Order do |order, token|
45
+ order.user == user || order.token && token == order.token
46
+ end
47
+ can :create, Order
48
+ #############################
49
+ can :read, Product
50
+ can :index, Product
51
+ #############################
52
+ can :read, Taxon
53
+ can :index, Taxon
54
+ #############################
55
+ end
56
+
57
+ #include any abilities registered by extensions, etc.
58
+ Ability.abilities.each do |clazz|
59
+ ability = clazz.send(:new, user)
60
+ @rules = rules + ability.send(:rules)
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,12 @@
1
+ Order.class_eval do
2
+ token_resource
3
+
4
+ # Associates the specified user with the order and destroys any previous association with guest user if
5
+ # necessary.
6
+ def associate_user!(user)
7
+ self.user = user
8
+ self.email = user.email
9
+ # disable validations since this can cause issues when associating an incomplete address during the address step
10
+ save(:validate => false)
11
+ end
12
+ end
@@ -0,0 +1,4 @@
1
+ class SpreeAuthConfiguration < Configuration
2
+ preference :registration_step, :boolean, :default => true
3
+ preference :signout_after_password_change, :boolean, :default => true
4
+ end
@@ -0,0 +1,14 @@
1
+ Spree::CurrentOrder.module_eval do
2
+
3
+ # Associate the new order with the currently authenticated user before saving
4
+ def before_save_new_order
5
+ @current_order.user ||= current_user
6
+ end
7
+
8
+ def after_save_new_order
9
+ # make sure the user has permission to access the order (if they are a guest)
10
+ return if current_user
11
+ session[:access_token] = @current_order.token
12
+ end
13
+
14
+ end
@@ -0,0 +1,3 @@
1
+ class TokenizedPermission < ActiveRecord::Base
2
+ belongs_to :permissable, :polymorphic => true
3
+ end
@@ -0,0 +1,85 @@
1
+ class User < ActiveRecord::Base
2
+
3
+ devise :database_authenticatable, :token_authenticatable, :registerable, :recoverable,
4
+ :rememberable, :trackable, :validatable, :encryptable, :encryptor => "authlogic_sha512"
5
+
6
+ has_many :orders
7
+ has_and_belongs_to_many :roles
8
+ belongs_to :ship_address, :foreign_key => "ship_address_id", :class_name => "Address"
9
+ belongs_to :bill_address, :foreign_key => "bill_address_id", :class_name => "Address"
10
+
11
+ before_save :check_admin
12
+ before_validation :set_login
13
+
14
+ # Setup accessible (or protected) attributes for your model
15
+ attr_accessible :email, :password, :password_confirmation, :remember_me, :persistence_token
16
+
17
+ scope :admin, lambda { includes(:roles).where("roles.name" => "admin") }
18
+ scope :registered, where("users.email NOT LIKE ?", "%@example.net")
19
+
20
+ # has_role? simply needs to return true or false whether a user has a role or not.
21
+ def has_role?(role_in_question)
22
+ roles.any? { |role| role.name == role_in_question.to_s }
23
+ end
24
+
25
+ # Creates an anonymous user. An anonymous user is basically an auto-generated +User+ account that is created for the customer
26
+ # behind the scenes and its completely transparently to the customer. All +Orders+ must have a +User+ so this is necessary
27
+ # when adding to the "cart" (which is really an order) and before the customer has a chance to provide an email or to register.
28
+ def self.anonymous!
29
+ token = User.generate_token(:persistence_token)
30
+ User.create(:email => "#{token}@example.net", :password => token, :password_confirmation => token, :persistence_token => token)
31
+ end
32
+
33
+ def self.admin_created?
34
+ User.admin.count > 0
35
+ end
36
+
37
+ def anonymous?
38
+ email =~ /@example.net$/
39
+ end
40
+
41
+ def deliver_password_reset_instructions!
42
+ reset_perishable_token!
43
+ UserMailer.password_reset_instructions(self).deliver
44
+ end
45
+
46
+ protected
47
+ def password_required?
48
+ !persisted? || password.present? || password_confirmation.present?
49
+ end
50
+
51
+ private
52
+
53
+ def check_admin
54
+ return if self.class.admin_created?
55
+ admin_role = Role.find_or_create_by_name "admin"
56
+ self.roles << admin_role
57
+ end
58
+
59
+ def set_login
60
+ # for now force login to be same as email, eventually we will make this configurable, etc.
61
+ self.login ||= self.email if self.email
62
+ end
63
+
64
+ # Generate a friendly string randomically to be used as token.
65
+ def self.friendly_token
66
+ ActiveSupport::SecureRandom.base64(15).tr('+/=', '-_ ').strip.delete("\n")
67
+ end
68
+
69
+ # Generate a token by looping and ensuring does not already exist.
70
+ def self.generate_token(column)
71
+ loop do
72
+ token = friendly_token
73
+ break token unless find(:first, :conditions => { column => token })
74
+ end
75
+ end
76
+
77
+ def self.current
78
+ Thread.current[:user]
79
+ end
80
+
81
+ def self.current=(user)
82
+ Thread.current[:user] = user
83
+ end
84
+
85
+ end
@@ -0,0 +1,13 @@
1
+ class UserMailer < ActionMailer::Base
2
+
3
+ def reset_password_instructions(user)
4
+ default_url_options[:host] = Spree::Config[:site_url]
5
+
6
+ @edit_password_reset_url = edit_user_password_url(:reset_password_token => user.reset_password_token)
7
+
8
+ mail(:to => user.email,
9
+ :subject => Spree::Config[:site_name] + ' ' + I18n.t("password_reset_instructions"))
10
+ end
11
+
12
+ end
13
+
@@ -0,0 +1,20 @@
1
+ <%= render "shared/error_messages", :target => @user %>
2
+ <h2><%= t("registration")%></h2>
3
+ <div id="registration">
4
+ <div id="account">
5
+ <%= render :file => 'user_sessions/new' %>
6
+ </div>
7
+ <% if Spree::Config[:allow_guest_checkout] %>
8
+ <div id="guest_checkout">
9
+ <%= render "shared/error_messages", :target => @order %>
10
+ <h2><%= t(:guest_user_account) %></h2>
11
+ <%= form_for @order, :url => update_checkout_registration_path, :html => { :method => :put, :id => "checkout_form_registration"} do |f| %>
12
+ <p>
13
+ <%= f.label :email, t("email") %><br />
14
+ <%= f.text_field :email, :class => 'title' %>
15
+ </p>
16
+ <p><%= submit_tag t("continue"), :class => 'button primary' %></p>
17
+ <% end %>
18
+ </div>
19
+ <% end %>
20
+ </div>
@@ -0,0 +1,8 @@
1
+ <% if current_user %>
2
+ <ul id="login-nav">
3
+ <li><%= t('logged_in_as') %>: <%= current_user.email %></li>
4
+ <li><%= link_to t('account'), edit_user_path(current_user) %></li>
5
+ <li><%= link_to t('logout'), destroy_user_session_path %></li>
6
+ <li><%= link_to t('store'), products_path %></li>
7
+ </ul>
8
+ <% end %>
@@ -0,0 +1,9 @@
1
+ <% if flash.any? %>
2
+ <div id="flash">
3
+ <% flash.each do |key, value| %>
4
+ <p>
5
+ <%= value %>
6
+ </p>
7
+ <% end %>
8
+ </div>
9
+ <% end%>
@@ -0,0 +1,20 @@
1
+ <%= form_for(:user, :url => user_session_path) do |f| %>
2
+ <div id='password-credentials'>
3
+ <p>
4
+ <%= f.label(:email, t("email")) %><br />
5
+ <%= f.text_field('email', :class => 'title') %>
6
+ </p>
7
+ <p>
8
+ <%= f.label :password, t("password") %><br />
9
+ <%= f.password_field 'password', :class => 'title' %>
10
+ </p>
11
+ </div>
12
+ <p>
13
+ <label>
14
+ <%= f.check_box :remember_me %>
15
+ <%= f.label :remember_me, t('remember_me') %>
16
+ </label>
17
+ </p>
18
+
19
+ <p><%= submit_tag t("log_in"), :class => 'button primary'%></p>
20
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <% if current_user %>
2
+ <li><%= link_to t('my_account'), account_path %></li>
3
+ <li><%= link_to t('logout'), destroy_user_session_path %></li>
4
+ <% else %>
5
+ <li><%= link_to t('log_in'), login_path %></li>
6
+ <% end %>
@@ -0,0 +1,17 @@
1
+ <p>
2
+ <%= f.label :email, t("email") %><br />
3
+ <%= f.text_field :email, :class => 'title' %>
4
+ </p>
5
+ <div id="password-credentials">
6
+ <p>
7
+ <%= f.label :password, t("password") %><br />
8
+ <%= f.password_field :password, :class => 'title' %>
9
+ </p>
10
+
11
+ <p>
12
+ <%= f.label :password_confirmation, t(:confirm_password) %><br />
13
+ <%= f.password_field :password_confirmation, :class => 'title' %>
14
+ </p>
15
+ </div>
16
+
17
+ <%= hook :signup_below_password_fields %>
File without changes
@@ -0,0 +1,10 @@
1
+ A request to reset your password has been made.
2
+ If you did not make this request, simply ignore this email.
3
+
4
+ If you did make this request just click the link below:
5
+
6
+ <%= @edit_password_reset_url %>
7
+
8
+ If the above URL does not work try copying and pasting it into your browser.
9
+ If you continue to have problem please feel free to contact us.
10
+
@@ -0,0 +1,15 @@
1
+ <%= render "shared/error_messages", :target => @user %>
2
+ <h1><%= t(:change_my_password) %></h1>
3
+
4
+ <%= form_for @user, :url => user_password_path, :html => {:method => :put} do |f| %>
5
+ <p>
6
+ <%= f.label :password %><br />
7
+ <%= f.password_field :password %><br />
8
+ </p>
9
+ <p>
10
+ <%= f.label :password_confirmation %><br />
11
+ <%= f.password_field :password_confirmation %><br />
12
+ </p>
13
+ <%= f.hidden_field :reset_password_token %>
14
+ <%= f.submit t("update_password") %>
15
+ <% end %>
@@ -0,0 +1,13 @@
1
+ <h1><%= t(:forgot_password) %></h1>
2
+
3
+ <p><%= t(:instructions_to_reset_password) %></p>
4
+
5
+ <%= form_for User.new, :as => :user, :url => user_password_path do |f| %>
6
+ <p>
7
+ <label><%= t(:email) %>:</label><br />
8
+ <%= f.email_field :email %>
9
+ </p>
10
+ <p>
11
+ <%= f.submit t("reset_password") %>
12
+ </p>
13
+ <% end %>
@@ -0,0 +1,23 @@
1
+ <% @body_id = 'signup' %>
2
+
3
+ <%= render "shared/error_messages", :target => @user %>
4
+
5
+ <div id="new-customer">
6
+ <h2><%= t("new_customer") %></h2>
7
+
8
+ <%= hook :signup do %>
9
+
10
+ <%= form_for(:user, :url => registration_path(@user)) do |f| %>
11
+
12
+ <%= hook :signup_inside_form do %>
13
+ <%= render 'shared/user_form', :f => f %>
14
+ <p><%= submit_tag t("create"), :class => 'button primary' %></p>
15
+ <% end %>
16
+
17
+ <% end %>
18
+ <%= t("or") %> <%= link_to t("login_as_existing"), login_path %>
19
+ <% end %>
20
+
21
+ </div>
22
+
23
+ <%= hook :login_extras %>
@@ -0,0 +1,4 @@
1
+ <div style="height:50px; padding-top: 20px">
2
+ <strong><%= t("authorization_failure")%></strong>
3
+ </div>
4
+ <!-- Add your own custom access denied message here if you like -->
@@ -0,0 +1,13 @@
1
+ <% if flash[:alert] %>
2
+ <div class="flash errors"><%= flash[:alert] %></div>
3
+ <% end %>
4
+
5
+ <% @body_id = 'login' %>
6
+ <div id="existing-customer">
7
+ <h2><%= t("login_as_existing") %></h2>
8
+ <%= hook :login do %>
9
+ <%= render :partial => 'shared/login' %>
10
+ <%= t("or") %> <%= link_to t("create_a_new_account"), signup_path %> | <%= link_to t("forgot_password"), new_user_password_path %>
11
+ <% end %>
12
+ </div>
13
+ <%= hook :login_extras %>
@@ -0,0 +1,11 @@
1
+ <%= render "shared/error_messages", :target => @user %>
2
+
3
+ <h1><%= t("editing_user") %></h1>
4
+
5
+ <%= form_for(@user, :html => { :method => :put }) do |f| %>
6
+ <%= render 'shared/user_form', :f => f %>
7
+ <p>
8
+ <%=submit_tag t("update") %>
9
+ </p>
10
+ <% end %>
11
+
@@ -0,0 +1,50 @@
1
+ <h1><%= t("my_account") %></h1>
2
+
3
+ <%= hook :account_summary do %>
4
+
5
+ <table>
6
+ <tr>
7
+ <td><%= t("email") %>:</td>
8
+ <td>
9
+ <%= @user.email %>
10
+ </td>
11
+ </tr>
12
+ </table>
13
+ <p><%= link_to t('edit'), edit_account_path %></p>
14
+
15
+ <% end %>
16
+
17
+ <%= hook :account_my_orders do %>
18
+
19
+ <h2><%= t("my_orders") %></h2>
20
+ <% if @orders.present? %>
21
+ <table class="order-summary" width="545">
22
+ <thead>
23
+ <tr>
24
+ <th><%= t("order_number") %></th>
25
+ <th><%= t("order_date") %></th>
26
+ <th><%= t("status") %></th>
27
+ <th><%= t("payment_state") %></th>
28
+ <th><%= t("shipment_state") %></th>
29
+ <th><%= t("total") %></th>
30
+ </tr>
31
+ </thead>
32
+ <tbody>
33
+ <% @orders.each do |order| %>
34
+ <tr class="<%= cycle('even', 'odd') %>">
35
+ <td><%= link_to order.number, order_url(order) %></td>
36
+ <td><%=order.created_at.to_date%></td>
37
+ <td><%= t(order.state).titleize %></td>
38
+ <td><%= t("payment_states.#{order.payment_state}") if order.payment_state %></td>
39
+ <td><%= t("shipment_states.#{order.shipment_state}") if order.shipment_state %></td>
40
+ <td><%= number_to_currency order.total %></td>
41
+ </tr>
42
+ <% end %>
43
+ </tbody>
44
+ </table>
45
+ <% else %>
46
+ <p><%= t(:you_have_no_orders_yet) %></p>
47
+ <% end %>
48
+ <br />
49
+
50
+ <% end %>