radiant-users-extension 0.0.5 → 2.1.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/.gitignore +1 -0
  2. data/MIT-LICENCE +19 -0
  3. data/README.md +69 -16
  4. data/Rakefile +25 -11
  5. data/app/helpers/admin/users_helper.rb +5 -0
  6. data/app/models/administrator.rb +3 -0
  7. data/app/models/designer.rb +3 -0
  8. data/app/models/user.rb +82 -0
  9. data/app/models/visitor.rb +3 -0
  10. data/app/views/admin/users/_fields.html.haml +49 -0
  11. data/app/views/admin/users/_form.html.haml +6 -0
  12. data/app/views/admin/users/remove.html.haml +16 -0
  13. data/app/views/confirmations/new.html.haml +13 -0
  14. data/app/views/devise_mailer/confirmation_instructions.html.haml +9 -0
  15. data/app/views/devise_mailer/reset_password_instructions.html.haml +15 -0
  16. data/app/views/devise_mailer/unlock_instructions.html.haml +12 -0
  17. data/app/views/mailer/confirmation_instructions.html.haml +4 -0
  18. data/app/views/mailer/reset_password_instructions.html.haml +6 -0
  19. data/app/views/mailer/unlock_instructions.html.haml +5 -0
  20. data/app/views/passwords/edit.html.haml +17 -0
  21. data/app/views/passwords/new.html.haml +14 -0
  22. data/app/views/registrations/edit.html.haml +32 -0
  23. data/app/views/registrations/new.html.haml +30 -0
  24. data/app/views/sessions/new.html.haml +27 -0
  25. data/app/views/shared/_links.html.haml +42 -0
  26. data/app/views/shared/_version.html.haml +5 -0
  27. data/app/views/unlocks/new.html.haml +9 -0
  28. data/config/initializers/devise.rb +12 -0
  29. data/config/initializers/radiant_config.rb +3 -0
  30. data/config/initializers/radiant_devise_encryptor.rb +10 -0
  31. data/config/locales/devise.en.yml +35 -0
  32. data/config/locales/en.yml +8 -0
  33. data/config/routes.rb +11 -6
  34. data/db/migrate/20110105024337_change_users_to_devise.rb +94 -0
  35. data/db/migrate/20110105150917_add_class_name_field.rb +9 -0
  36. data/db/migrate/20110107032850_move_permissions_to_class.rb +30 -0
  37. data/db/migrate/20110118103247_change_admin_to_administrator.rb +18 -0
  38. data/features/support/env.rb +1 -1
  39. data/lib/login_system.rb +81 -0
  40. data/lib/radiant-users-extension.rb +2 -1
  41. data/lib/radiant-users-extension/version.rb +3 -0
  42. data/lib/tasks/users_extension_tasks.rake +3 -2
  43. data/lib/users/controllers/admin/resource_controller.rb +15 -0
  44. data/lib/users/controllers/admin/welcome_controller.rb +19 -0
  45. data/lib/users/controllers/application_controller.rb +25 -0
  46. data/lib/users/controllers/devise/confirmations_controller.rb +17 -0
  47. data/lib/users/controllers/devise/passwords_controller.rb +17 -0
  48. data/lib/users/controllers/devise/registrations_controller.rb +17 -0
  49. data/lib/users/controllers/devise/sessions_controller.rb +17 -0
  50. data/lib/users/controllers/single_form_body_styles.rb +27 -0
  51. data/lib/users/controllers/site_controller.rb +13 -0
  52. data/lib/users/lib/devise/controllers/internal_helpers.rb +31 -0
  53. data/lib/users/tags/core.rb +11 -13
  54. data/lib/users/tags/helper.rb +13 -0
  55. data/lib/users/tags/helpers.rb +1 -7
  56. data/radiant-users-extension.gemspec +73 -13
  57. data/spec/datasets/devise_users_dataset.rb +56 -0
  58. data/spec/models/user_spec.rb +125 -13
  59. data/spec/spec.opts +3 -4
  60. data/spec/spec_helper.rb +15 -4
  61. data/spec/tags/core_spec.rb +128 -0
  62. data/users_extension.rb +27 -9
  63. metadata +105 -21
  64. data/db/migrate/20100311014641_add_api_key_to_users.rb +0 -14
  65. data/db/migrate/20100311021835_add_access_to_user.rb +0 -9
  66. data/lib/users/lib/login_system.rb +0 -48
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ pkg
data/MIT-LICENCE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) <2011> by <Dirk Kelly [The Frontier Group Pty Ltd]>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md CHANGED
@@ -1,31 +1,84 @@
1
- # Radiant Users Extension
1
+ # Users
2
2
 
3
- Hook standard Radiant users to provide front end user creation and login.
3
+ * Radiant is lovely <3
4
+ * The user authentication system works.
5
+ * This extension replaces that working system with Devise.
6
+ * Devise also works
7
+ * Radiant-Users-Extension is also lovely <3
4
8
 
5
- A good example comes from [radiant-shop-extension](http://github.com/dirkkelly/radiant-shop-extension) in the use of customers
9
+ # Installing
10
+
11
+ git clone git@github.com:dirkkelly/radiant-users-extension vendor/extensions/users
12
+ cd vendor/extensions/users
13
+ git checkout devise
14
+ cd ../../../
15
+ rake radiant:extensions:users:migrate
6
16
 
7
- ## Create a Model
17
+ # Registrations
8
18
 
9
- class ShopCustomer < User
10
- include Users::Models::User::Scoped
19
+ You will need to override the Devise definition in the user model
20
+
21
+ User.class_eval do
22
+
23
+ devise :database_authenticatable, :registerable, :confirmable, :recoverable, :rememberable, :token_authenticatable, :validatable
24
+
25
+ end
26
+
27
+ You can set a custom class_name on new registrations
28
+
29
+ User.class_eval do
30
+
31
+ protected
32
+
33
+ def set_class_name
34
+ self.class_name ||= "Visitor"
35
+ end
36
+
11
37
  end
12
38
 
13
- When a customer is created the access attributes present status will prevent them from accessing the administration system.
39
+ # Migration
40
+
41
+ * Passwords do not need to change, the migration will take care of updating these
42
+ * Emails are now required for every user. You will get warned of users with missing emails and a dummy address _set@email.com_ will be applied
43
+
44
+ Field changes
45
+
46
+ login => username (setter and getter abstracted out)
47
+ password => encrypted_password
48
+ salt => password_salt
14
49
 
15
- ## Define Their Welcome Page
50
+ # Inheriting Classes
16
51
 
17
- Radiant::Config['users.shop_customer.redirect'] = '/cart'
52
+ _actually, this doesn't exist yet_
18
53
 
19
- ## API Access
54
+ User has a field `class_name`, when you inherit a class this will get set.
20
55
 
21
- Login Candy provided us with authentication hooks allowing for API login, there is currently no login mechanism. Contributions are welcome
56
+ If this field is not nil, the user will not have access to the administration system.
22
57
 
23
- # Installation
58
+ # Development and Testing
24
59
 
25
- Gemfile
60
+ This extension uses the following gems, define them in a development and test group.
26
61
 
27
- gem 'radiant-users-extension', :require => nil
62
+ group :development do
63
+ gem 'ruby-debug', '~> 0.10.3'
64
+ gem 'jeweler', '~> 1.5.2'
65
+ gem 'rspec-rails', '~> 1.3.2'
66
+ gem 'remarkable', '3.1.12', :git => 'https://github.com/joerichsen/remarkable.git', :branch => 'rspec1-compat'
67
+ gem 'remarkable_rails', '3.1.12', :require => 'remarkable_rails'
68
+ end
69
+
70
+ group :test do
71
+ gem 'rspec', '~> 1.3.1'
72
+ gem 'rspec-rails', '~> 1.3.2'
73
+ gem 'remarkable', '3.1.12', :git => 'https://github.com/joerichsen/remarkable.git', :branch => 'rspec1-compat'
74
+ gem 'remarkable_rails', '3.1.12', :require => 'remarkable_rails'
75
+ gem 'cucumber-rails', '~> 0.2.4'
76
+ gem 'database_cleaner', '~> 0.4.3'
77
+ gem 'webrat', '~> 0.6.0'
78
+ gem 'rr', '~> 0.10.11'
79
+ gem 'rcov', '~> 0.9.9'
80
+ end
28
81
 
29
- config/environment.rb
82
+ # LICENCE
30
83
 
31
- config.gem 'radiant-users-extension', :lib => false
84
+ This extension was developed by [Dirk Kelly](http://twitter.com/dirkkelly) on [The Frontier Group's](http://twitter.com/frontiergroup) Time. It is licenced as MIT.
data/Rakefile CHANGED
@@ -1,22 +1,36 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "radiant-users-extension/version"
3
+
1
4
  begin
2
5
  require 'jeweler'
3
6
  Jeweler::Tasks.new do |gem|
4
- gem.name = "radiant-users-extension"
5
- gem.summary = %Q{Users Extension for Radiant CMS}
6
- gem.description = %Q{Users creates support for non-admin users with API access}
7
- gem.email = "dk@squaretalent.com"
8
- gem.homepage = "http://github.com/dirkkelly/radiant-users-extension"
9
- gem.authors = ["Christopher Rankin", "Dirk Kelly"]
7
+ gem.name = "radiant-users-extension"
8
+ gem.version = RadiantUsersExtension::VERSION
9
+ gem.platform = Gem::Platform::RUBY
10
+ gem.authors = ["Dirk Kelly"]
11
+ gem.email = ["dk@dirkkelly.com"]
12
+ gem.homepage = "http://github.com/dirkkelly/radiant-users-extension"
13
+ gem.summary = %q{Users for Radiant CMS}
14
+ gem.description = %q{Makes Radiant better by adding users!}
15
+
16
+ gem.files = `git ls-files`.split("\n")
17
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ gem.require_paths = ["lib"]
20
+
21
+ gem.add_dependency 'radiant', '~> 0.9'
22
+ gem.add_dependency 'devise', '~> 1.0.9'
23
+
24
+ gem.post_install_message = %{
25
+ Add this to your radiant project with:
26
+ config.gem 'radiant-users-extension', :version => '#{RadiantUsersExtension::VERSION}'
27
+ }
10
28
  end
11
29
  Jeweler::GemcutterTasks.new
12
30
  rescue LoadError
13
- puts "Jeweler (or a dependency) not available. This is only required if you plan to package users as a gem."
31
+ puts "Jeweler (or a dependency) not available. This is only required if you plan to package shop as a gem."
14
32
  end
15
33
 
16
- # In rails 1.2, plugins aren't available in the path until they're loaded.
17
- # Check to see if the rspec plugin is installed first and require
18
- # it if it is. If not, use the gem version.
19
-
20
34
  # Determine where the RSpec plugin is by loading the boot
21
35
  unless defined? RADIANT_ROOT
22
36
  ENV["RAILS_ENV"] = "test"
@@ -0,0 +1,5 @@
1
+ module Admin::UsersHelper
2
+ def roles(user)
3
+ user.class_name
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ class Administrator < User
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class Designer < User
2
+
3
+ end
@@ -0,0 +1,82 @@
1
+ class User < ActiveRecord::Base
2
+
3
+ @@authorized_types = [ 'Administrator', 'Designer', 'User' ]
4
+
5
+ devise :database_authenticatable, :confirmable, :recoverable, :rememberable, :token_authenticatable, :validatable
6
+ # When inheriting this can raise an exception on the new models
7
+
8
+ attr_accessor :login, :new_class_name
9
+
10
+ # Default Order
11
+ default_scope :order => 'name'
12
+
13
+ set_inheritance_column :class_name
14
+
15
+ # Associations
16
+ belongs_to :created_by, :class_name => 'User'
17
+ belongs_to :updated_by, :class_name => 'User'
18
+
19
+ before_validation :set_class_name
20
+
21
+ validates_presence_of :name
22
+ validates_presence_of :class_name # Has no effect
23
+
24
+ def login
25
+ self[:username]
26
+ end
27
+
28
+ def login=(username)
29
+ self[:username] = username
30
+ end
31
+
32
+ def new_class_name
33
+ self[:class_name]
34
+ end
35
+
36
+ def new_class_name=(class_name)
37
+ @current_user = UserActionObserver.current_user
38
+ self[:class_name] = @current_user.has_role?(:admin) ? class_name : self[:class_name]
39
+ end
40
+
41
+ def admin?
42
+ has_role?(:admin)
43
+ end
44
+
45
+ def designer?
46
+ has_role?(:designer)
47
+ end
48
+
49
+ def authorized?
50
+ @@authorized_types.include?(class_name)
51
+ end
52
+
53
+ def has_role?(role)
54
+ class_name.downcase.to_sym == role.to_s.downcase.to_sym
55
+ end
56
+
57
+ class << self
58
+ def unprotected_attributes
59
+ @unprotected_attributes ||= [:name, :email, :username, :login, :password, :password_confirmation, :locale]
60
+ end
61
+
62
+ def unprotected_attributes=(array)
63
+ @unprotected_attributes = array.map{|att| att.to_sym }
64
+ end
65
+
66
+ def find_for_authentication(conditions)
67
+ login = conditions.delete(:login)
68
+ find(:first, :conditions => ["username = ? OR email = ?", login, login])
69
+ end
70
+ end
71
+
72
+ protected
73
+
74
+ def password_required?
75
+ new_record? || destroyed? || password.present? || password_confirmation.present?
76
+ end
77
+
78
+ def set_class_name
79
+ self[:class_name] ||= "User"
80
+ end
81
+
82
+ end
@@ -0,0 +1,3 @@
1
+ class Visitor < User
2
+
3
+ end
@@ -0,0 +1,49 @@
1
+ = hidden_field "user", "lock_version"
2
+
3
+ = render :partial => 'avatar' unless @user.new_record?
4
+
5
+ = render_region :form_top, :locals => {:f => f}
6
+
7
+ - render_region :form, :locals => {:f => f} do |form|
8
+ - form.edit_name do
9
+ %p
10
+ = f.label :name, t('name')
11
+ = f.text_field :name, :class => "textbox activate", :size => 32, :maxlength => 100, :object => :user
12
+
13
+ - form.edit_email do
14
+ %p
15
+ = f.label :email, t('email_address') , :class => "optional"
16
+ = f.text_field "email", :class => 'textbox', :size => 32, :maxlength => 255
17
+
18
+ - form.edit_username do
19
+ %p
20
+ = f.label :username, t('username')
21
+ = f.text_field :username, :class => "textbox", :size => 32, :maxlength => 40, :autocomplete => 'off'
22
+
23
+ - form.edit_password do
24
+ = render "password_fields", :f => f
25
+
26
+ - form.edit_roles do
27
+ %p
28
+ = f.label :new_class_name, t('role')
29
+ = f.text_field :new_class_name, :class => "textbox", :size => 32, :maxlength => 40, :autocomplete => 'off', :value => @user.class_name
30
+
31
+ - form.edit_locale do
32
+ %p
33
+ = f.label :locale, t('language')
34
+ = f.select "locale", available_locales_select
35
+
36
+ - form.edit_notes do
37
+ %p
38
+ = f.label :notes, t('notes'), :class => "optional"
39
+ ~ f.text_area "notes", :size => "53x4", :class => "textarea"
40
+
41
+ - render_region :form_bottom, :locals => {:f => f} do |form_bottom|
42
+ - form_bottom.edit_buttons do
43
+ %p.buttons
44
+ = save_model_button(@user)
45
+ = save_model_and_continue_editing_button(@user)
46
+ = t('or')
47
+ = link_to t('cancel'), admin_users_path
48
+ - form_bottom.edit_timestamp do
49
+ = updated_stamp @user
@@ -0,0 +1,6 @@
1
+ - if @user.new_record?
2
+ - form_for "user", :url => admin_users_path do |f|
3
+ = render :partial => "fields", :locals => { :f => f }
4
+ - else
5
+ - form_for "user", :url => admin_user_path(@user), :html => { :method => "put" } do |f|
6
+ = render :partial => "fields", :locals => { :f => f }
@@ -0,0 +1,16 @@
1
+ %h1= t('remove_user')
2
+
3
+ %p
4
+ = t('text.users.remove_warning')
5
+
6
+ %table.index#users
7
+ %tbody
8
+ %tr.node.level_1
9
+ %td.user
10
+ %span.title= @user.name
11
+
12
+ - form_tag admin_user_path(@user), :method => :delete, 'data-onsubmit_status'=>"Removing user&#8230;" do
13
+ %p.buttons
14
+ %input.button{:type=>"submit", :value => t('delete_user')}/
15
+ = t('or')
16
+ = link_to t('cancel'), admin_users_path
@@ -0,0 +1,13 @@
1
+ #single_form
2
+
3
+ %h1 Resend confirmation instructions
4
+
5
+ - form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post }) do |f|
6
+ %p
7
+ = f.label :email
8
+ = f.text_field :email, :class => 'password textbox', :maxlength => 40, :size => 40, :type => "email"
9
+ %p.buttons
10
+ = f.submit "Resend confirmation instructions"
11
+ = render "shared/links"
12
+
13
+ = render "shared/version"
@@ -0,0 +1,9 @@
1
+ %p
2
+ Welcome
3
+ =@resource.email
4
+
5
+ %p
6
+ You can confirm your account through the link below:
7
+
8
+ %p
9
+ = link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token)
@@ -0,0 +1,15 @@
1
+ %p
2
+ Hello
3
+ = @resource.email
4
+
5
+ %p
6
+ Someone has requested a link to change your password, and you can do this through the link below.
7
+
8
+ %p
9
+ = link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token)
10
+
11
+ %p
12
+ If you didn't request this, please ignore this email.
13
+
14
+ %p
15
+ Your password won't change until you access the link above and create a new one.
@@ -0,0 +1,12 @@
1
+ %p
2
+ Hello
3
+ = @resource.email
4
+
5
+ %p
6
+ Your account has been locked due to an excessive amount of unsuccessful sign in attempts.
7
+
8
+ %p
9
+ Click the link below to unlock your account:
10
+
11
+ %p
12
+ = link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @resource.unlock_token)
@@ -0,0 +1,4 @@
1
+ %p
2
+ Welcome #{@resource.email}!
3
+ %p You can confirm your account through the link below:
4
+ %p= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token)
@@ -0,0 +1,6 @@
1
+ %p
2
+ Hello #{@resource.email}!
3
+ %p Someone has requested a link to change your password, and you can do this through the link below.
4
+ %p= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token)
5
+ %p If you didn't request this, please ignore this email.
6
+ %p Your password won't change until you access the link above and create a new one.
@@ -0,0 +1,5 @@
1
+ %p
2
+ Hello #{@resource.email}!
3
+ %p Your account has been locked due to an excessive amount of unsuccessful sign in attempts.
4
+ %p Click the link below to unlock your account:
5
+ %p= link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @resource.unlock_token)
@@ -0,0 +1,17 @@
1
+ #single_form
2
+
3
+ %h1 Change your password
4
+
5
+ - form_for resource_name, resource, :url => password_path(resource_name), :html => { :method => :put } do |f|
6
+ = f.hidden_field :reset_password_token
7
+ %p
8
+ = f.label :password, t('new_password')
9
+ = f.password_field :password, :class => 'password textbox', :maxlength => 40, :size => 40
10
+ %p
11
+ = f.label :password_confirmation, t('password_confirmation')
12
+ = f.password_field :password_confirmation, :class => 'password textbox', :maxlength => 40, :size => 40
13
+ %p.buttons
14
+ = f.submit "Change my password"
15
+ = render "shared/links"
16
+
17
+ = render "shared/version"