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.
- data/LICENSE +26 -0
- data/README.md +36 -0
- data/app/controllers/admin_controller_decorator.rb +7 -0
- data/app/controllers/admin_orders_controller_decorator.rb +15 -0
- data/app/controllers/admin_resource_controller_decorator.rb +3 -0
- data/app/controllers/checkout_controller_decorator.rb +42 -0
- data/app/controllers/orders_controller_decorator.rb +17 -0
- data/app/controllers/resource_controller_decorator.rb +25 -0
- data/app/controllers/spree/base_controller_decorator.rb +49 -0
- data/app/controllers/user_passwords_controller.rb +20 -0
- data/app/controllers/user_registrations_controller.rb +64 -0
- data/app/controllers/user_sessions_controller.rb +81 -0
- data/app/controllers/users_controller.rb +54 -0
- data/app/helpers/users_helper.rb +13 -0
- data/app/models/ability.rb +64 -0
- data/app/models/order_decorator.rb +12 -0
- data/app/models/spree_auth_configuration.rb +4 -0
- data/app/models/spree_current_order_decorator.rb +14 -0
- data/app/models/tokenized_permission.rb +3 -0
- data/app/models/user.rb +85 -0
- data/app/models/user_mailer.rb +13 -0
- data/app/views/checkout/registration.html.erb +20 -0
- data/app/views/layouts/admin/_login_nav.html.erb +8 -0
- data/app/views/shared/_flashes.html.erb +9 -0
- data/app/views/shared/_login.html.erb +20 -0
- data/app/views/shared/_login_bar.html.erb +6 -0
- data/app/views/shared/_user_form.html.erb +17 -0
- data/app/views/shared/unauthorized.html.erb +0 -0
- data/app/views/user_mailer/reset_password_instructions.text.erb +10 -0
- data/app/views/user_passwords/edit.html.erb +15 -0
- data/app/views/user_passwords/new.html.erb +13 -0
- data/app/views/user_registrations/new.html.erb +23 -0
- data/app/views/user_sessions/authorization_failure.html.erb +4 -0
- data/app/views/user_sessions/new.html.erb +13 -0
- data/app/views/users/edit.html.erb +11 -0
- data/app/views/users/show.html.erb +50 -0
- data/config/cucumber.yml +10 -0
- data/config/initializers/devise.rb +136 -0
- data/config/locales/en.yml +46 -0
- data/config/routes.rb +28 -0
- data/db/migrate/20101026184950_rename_columns_for_devise.rb +39 -0
- data/db/migrate/20101214150824_convert_user_remember_field.rb +11 -0
- data/db/migrate/20101217012656_create_tokenized_permissions.rb +18 -0
- data/db/migrate/20101219201531_tokens_for_legacy_orders.rb +12 -0
- data/db/sample/users.rb +53 -0
- data/lib/apispree_auth.rb +29 -0
- data/lib/spree/auth/config.rb +22 -0
- data/lib/spree/token_resource.rb +23 -0
- data/lib/spree_auth_hooks.rb +6 -0
- data/lib/tasks/auth.rake +8 -0
- data/lib/tasks/install.rake +23 -0
- 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,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
|
data/app/models/user.rb
ADDED
@@ -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,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,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,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 %>
|