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
@@ -0,0 +1,14 @@
1
+ #single_form
2
+
3
+ %h1= t('devise.passwords.link')
4
+
5
+ - form_for(resource_name, resource, :url => password_path(resource_name), :html => { :method => :post }) do |f|
6
+ %p
7
+ = f.label :email, t('email')
8
+ = f.text_field :email, :class => 'textbox', :maxlength => 40, :size => 40, :type => "email"
9
+
10
+ %p.buttons
11
+ = f.submit t('devise.passwords.button')
12
+ = render "shared/links"
13
+
14
+ = render "shared/version"
@@ -0,0 +1,32 @@
1
+ #single_form
2
+
3
+ %h1
4
+ #{t('edit')} #{resource_name.to_s.humanize}
5
+
6
+ %h2
7
+ #{link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete}
8
+
9
+ - form_for(resource_name, resource, :url => registration_path(resource_name), :html => { :method => :put }) do |f|
10
+ %p
11
+ = f.label :name, t('name')
12
+ = f.text_field :name, :class => 'textbox', :maxlength => 40, :size => 40
13
+
14
+ %p
15
+ = f.label :email, t('email')
16
+ = f.text_field :email, :class => 'textbox', :maxlength => 40, :size => 40, :type => "email"
17
+
18
+ %p
19
+ %em (leave blank if you don't want to change it)
20
+ = f.label :password, t('password')
21
+ = f.password_field :password, :class => 'textbox', :maxlength => 40, :size => 40
22
+
23
+ %p
24
+ %em (We need this to save changes)
25
+ = f.label :current_password, t('current_password')
26
+ = f.password_field :current_password, :class => 'textbox', :maxlength => 40, :size => 40
27
+
28
+ %p.buttons
29
+ = f.submit t('buttons.save_and_continue')
30
+ = render "shared/links"
31
+
32
+ = render "shared/version"
@@ -0,0 +1,30 @@
1
+ #single_form
2
+
3
+ %h1= t('devise.registrations.link')
4
+
5
+ - form_for(resource_name, resource, :url => registration_path(resource_name)) do |f|
6
+ %p
7
+ = f.label :name, t('name')
8
+ = f.text_field :name, :class => 'textbox', :maxlength => 40, :size => 40
9
+
10
+ %p
11
+ = f.label :username, t('username')
12
+ = f.text_field :username, :class => 'textbox', :maxlength => 40, :size => 40
13
+
14
+ %p
15
+ = f.label :email, t('email')
16
+ = f.text_field :email, :class => 'textbox', :maxlength => 40, :size => 40, :type => "email"
17
+
18
+ %p
19
+ = f.label :password, t('password')
20
+ = f.password_field :password, :class => 'textbox', :maxlength => 40, :size => 40
21
+
22
+ %p
23
+ = f.label :password_confirmation, t('password_confirmation')
24
+ = f.password_field :password_confirmation, :class => 'textbox', :maxlength => 40, :size => 40
25
+
26
+ %p.buttons
27
+ = f.submit t('devise.registrations.link')
28
+ = render "shared/links"
29
+
30
+ = render "shared/version"
@@ -0,0 +1,27 @@
1
+ #single_form
2
+
3
+ %h1
4
+ = t('devise.sessions.link')
5
+
6
+ - if devise_mapping.registerable?
7
+ %h2
8
+ (or 
9
+ %span<>= link_to(t('devise.registrations.link'), new_registration_path(resource_name))
10
+ )
11
+
12
+ - form_for(resource_name, resource, :url => session_path(resource_name)) do |f|
13
+ %p
14
+ = f.label :login, t('username_or_email')
15
+ = f.text_field :login, :class => 'textbox', :maxlength => 40, :size => 40
16
+ %p
17
+ = f.label :password, t('password')
18
+ = f.password_field :password, :class => 'textbox password', :maxlength => 40, :size => 40
19
+ - if devise_mapping.rememberable?
20
+ %p.remember_me
21
+ = f.check_box :remember_me, :class => 'checkbox', :checked => 'false', :value => 1
22
+ = f.label :remember_me, t('remember_me_in_this_browser'), :class => "checkbox"
23
+ %p.buttons
24
+ = f.submit t('login')
25
+ = render "shared/links"
26
+
27
+ = render "shared/version"
@@ -0,0 +1,42 @@
1
+ - unless user_signed_in?
2
+ %span.links
3
+ - if controller_name != 'sessions'
4
+ = link_to t('devise.sessions.link'), new_session_path(resource_name)
5
+ - if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations'
6
+ = link_to t('devise.passwords.link'), new_password_path(resource_name)
7
+ - if devise_mapping.confirmable? && controller_name != 'confirmations'
8
+ = link_to t('devise.confirmations.link'), new_confirmation_path(resource_name)
9
+ - if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks'
10
+ = link_to t('devise.unlocks.link'), new_unlock_path(resource_name)
11
+
12
+ %style{:type=>"text/css"}
13
+ :sass
14
+ #content
15
+
16
+ #single_form
17
+ padding-bottom: 10px !important
18
+
19
+ h2
20
+ position: absolute
21
+ top: 20px
22
+ right: 25px
23
+ font-size: 0.8em
24
+
25
+ em
26
+ float: right
27
+
28
+ p.buttons
29
+ padding-top: 10px
30
+
31
+ .links
32
+ position: absolute
33
+ dispaly: block
34
+ bottom: 20px
35
+ right: 25px
36
+ overflow: hidden
37
+
38
+ a
39
+ float: right
40
+ clear: right
41
+ color: #000
42
+ font-size: 0.75em
@@ -0,0 +1,5 @@
1
+ %p.version
2
+ = t('powered_by')
3
+ %a{ :href => "http://radiantcms.org" } Radiant CMS
4
+ = t('version')
5
+ = Radiant.loaded_via_gem? ? "#{Radiant::Version} (gem)." : "#{Radiant::Version}."
@@ -0,0 +1,9 @@
1
+ %h2 Resend unlock instructions
2
+ = form_for(resource, :as => resource_name, :url => unlock_path(resource_name), :html => { :method => :post }) do |f|
3
+ = devise_error_messages!
4
+ %p
5
+ = f.label :email
6
+ %br/
7
+ = f.email_field :email
8
+ %p= f.submit "Resend unlock instructions"
9
+ = render :partial => "devise/shared/links"
@@ -0,0 +1,12 @@
1
+ Devise.setup do |config|
2
+
3
+ config.mailer_sender = "please-change-me@config-initializers-devise.com"
4
+ config.use_default_scope = true
5
+ config.default_scope = :user
6
+ config.scoped_views = true
7
+
8
+ config.encryptor = :radiant
9
+
10
+ config.authentication_keys = [:login]
11
+
12
+ end
@@ -0,0 +1,3 @@
1
+ Radiant.config do |config|
2
+ # config.define "setting.name", :default => 'value', :select_from => ['foo', 'bar']
3
+ end
@@ -0,0 +1,10 @@
1
+ module Devise
2
+ module Encryptors
3
+ class Radiant < Base
4
+ def self.digest(password, stretches, salt, pepper)
5
+ str = [password, salt].flatten.compact.join
6
+ Digest::SHA1.hexdigest("--#{salt}--#{password}--")
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,35 @@
1
+ en:
2
+ devise:
3
+ sessions:
4
+ link: 'Login'
5
+ signed_in: 'Logged in successfully.'
6
+ signed_out: 'Logged out successfully.'
7
+ unauthenticated: 'You need to log in or sign up before continuing.'
8
+ unconfirmed: 'You have to confirm your account before continuing.'
9
+ locked: 'Your account is locked.'
10
+ invalid: 'Invalid email or password.'
11
+ invalid_token: 'Invalid authentication token.'
12
+ timeout: 'Your session expired, please sign in again to continue.'
13
+ inactive: 'Your account was not activated yet.'
14
+ passwords:
15
+ link: 'Forgot password?'
16
+ button: 'Send reset instructions'
17
+ send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
18
+ updated: 'Your password was changed successfully. You are now signed in.'
19
+ confirmations:
20
+ link: "Didn't receive confirmation instructions?"
21
+ send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
22
+ confirmed: 'Your account was successfully confirmed. You are now signed in.'
23
+ registrations:
24
+ link: 'Sign up'
25
+ signed_up: 'You have signed up successfully.'
26
+ updated: 'You updated your account successfully.'
27
+ destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
28
+ unlocks:
29
+ link: "Didn't receive unlock instructions?"
30
+ send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
31
+ unlocked: 'Your account was successfully unlocked. You are now signed in.'
32
+ mailer:
33
+ confirmation_instructions: 'Confirmation instructions'
34
+ reset_password_instructions: 'Reset password instructions'
35
+ unlock_instructions: 'Unlock Instructions'
@@ -0,0 +1,8 @@
1
+ ---
2
+ en:
3
+ users: Users
4
+ email: 'E-mail Address'
5
+ new_password: 'New Password'
6
+ current_password: 'Current Password'
7
+ role: Role
8
+ roles: Roles
data/config/routes.rb CHANGED
@@ -1,8 +1,13 @@
1
1
  ActionController::Routing::Routes.draw do |map|
2
-
3
- map.with_options(:controller => 'admin/welcome') do |welcome|
4
- welcome.login 'login', :action => 'login'
5
- welcome.logout 'logout', :action => 'logout'
6
- end
7
-
2
+
3
+ map.devise_for :users, :path_names => { :sign_in => 'login', :sign_out => 'logout' }
4
+ map.new_user_session 'login', :controller => 'sessions', :action => 'new', :conditions => { :method => :get }
5
+ map.old_user_session 'admin/login', :controller => 'sessions', :action => 'new', :conditions => { :method => :get }
6
+ map.user_session 'login', :controller => 'sessions', :action => 'create', :conditions => { :method => :post }
7
+ map.destroy_user_session 'logout', :controller => 'sessions', :action => 'destroy', :conditions => { :method => :get }
8
+ map.old_destroy_user_session 'admin/logout', :controller => 'sessions', :action => 'destroy', :conditions => { :method => :get }
9
+
10
+ map.user_root_path 'users/root', :controller => 'admin/welcome', :action => 'index'
11
+ # This can redirect to anything by overiding ApplicationController#default_admin_path
12
+
8
13
  end
@@ -0,0 +1,94 @@
1
+ # create_table "users", :force => true do |t|
2
+ # t.string "name", :limit => 100
3
+ # t.string "email"
4
+ # t.string "login", :limit => 40, :default => "", :null => false
5
+ # t.string "password", :limit => 40
6
+ # t.datetime "created_at"
7
+ # t.datetime "updated_at"
8
+ # t.integer "created_by_id"
9
+ # t.integer "updated_by_id"
10
+ # t.boolean "admin", :default => false, :null => false
11
+ # t.boolean "designer", :default => false, :null => false
12
+ # t.text "notes"
13
+ # t.integer "lock_version", :default => 0
14
+ # t.string "salt"
15
+ # t.string "session_token"
16
+ # t.string "locale"
17
+ # end
18
+
19
+ # devise :database_authenticatable, :confirmable, :recoverable, :rememberable, :token_authenticatable
20
+
21
+ class ChangeUsersToDevise < ActiveRecord::Migration
22
+ def self.up
23
+ add_column :users, :encrypted_password, :string, :null => false, :default => "", :limit => 128
24
+ add_column :users, :password_salt, :string, :null => false, :default => ""
25
+ add_column :users, :username, :string, :null => false, :default => "", :limit => 40
26
+
27
+ add_column :users, :confirmation_token, :string
28
+ add_column :users, :confirmed_at, :date_time
29
+ add_column :users, :confirmation_sent_at, :date_time
30
+
31
+ add_column :users, :reset_password_token, :string
32
+
33
+ add_column :users, :remember_token, :string
34
+ add_column :users, :remember_created_at, :date_time
35
+
36
+ add_column :users, :authentication_token, :string
37
+
38
+ User.reset_column_information
39
+ puts "\n-- Migrating Users \n\n"
40
+ User.find_each do |user|
41
+ user[:username] = user[:login]
42
+ user[:encrypted_password] = user[:password]
43
+ user[:password_salt] = user[:salt]
44
+
45
+ if user[:email].present?
46
+ user[:email] = user[:email]
47
+ else
48
+ puts " WARNING: `#{user[:username]}` will need to set a real email address"
49
+ user[:email] = 'set@email.com'
50
+ end
51
+
52
+ user.confirm!
53
+ user.save!
54
+ end
55
+ puts "\n\n"
56
+
57
+ remove_column :users, :login
58
+ remove_column :users, :password
59
+ remove_column :users, :salt
60
+
61
+ end
62
+
63
+ def self.down
64
+
65
+ add_column :users, :login, :string, :limit => 40, :null => false, :default => ""
66
+ add_column :users, :password, :string, :limit => 40
67
+ add_column :users, :salt, :string
68
+
69
+ User.reset_column_information
70
+ User.find_each do |user|
71
+ user[:login] = user[:username]
72
+ user[:password] = user[:encrypted_password]
73
+ user[:salt] = user[:password_salt]
74
+
75
+ user.save!
76
+ end
77
+
78
+ remove_column :users, :encrypted_password
79
+ remove_column :users, :password_salt
80
+ remove_column :users, :username
81
+
82
+ remove_column :users, :confirmation_token
83
+ remove_column :users, :confirmed_at
84
+ remove_column :users, :confirmation_sent_at
85
+
86
+ remove_column :users, :reset_password_token
87
+
88
+ remove_column :users, :remember_token
89
+ remove_column :users, :remember_created_at
90
+
91
+ remove_column :users, :authentication_token
92
+
93
+ end
94
+ end
@@ -0,0 +1,9 @@
1
+ class AddClassNameField < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :users, :class_name, :string, :allow_blank => true
4
+ end
5
+
6
+ def self.down
7
+ remove_column :users, :class_name
8
+ end
9
+ end
@@ -0,0 +1,30 @@
1
+ class User < ActiveRecord::Base; end
2
+
3
+ class MovePermissionsToClass < ActiveRecord::Migration
4
+ def self.up
5
+
6
+ begin
7
+ User.find_each do |u|
8
+ class_name = "User"
9
+ class_name = "Designer" if u.designer == true
10
+ class_name = "Administrator" if u.admin == true
11
+
12
+ u.update_attribute(:class_name, class_name)
13
+ end
14
+ rescue
15
+ # You probably didn't need this then
16
+ end
17
+
18
+ remove_column :users, :admin
19
+ remove_column :users, :designer
20
+ end
21
+
22
+ def self.down
23
+ create_column :users, :admin, :boolean
24
+ create_column :users, :designer, :boolean
25
+ User.find_each do |u|
26
+ u.designer = true if u.has_role?(:designer)
27
+ u.admin = true if u.has_role?(:admin)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,18 @@
1
+ class User < ActiveRecord::Base; end
2
+
3
+ class ChangeAdminToAdministrator < ActiveRecord::Migration
4
+ def self.up
5
+
6
+ begin
7
+ User.find_each do |user|
8
+ user.update_attribute(:class_name, 'Administrator') if user.class_name == 'Admin'
9
+ end
10
+ rescue
11
+ # You probably didn't need this then
12
+ end
13
+ end
14
+
15
+ def self.down
16
+ raise ActiveRecord::IrreversibleMigration
17
+ end
18
+ end
@@ -12,5 +12,5 @@ Cucumber::Rails::World.class_eval do
12
12
  Dataset::Resolver.default = Dataset::DirectoryResolver.new("#{RADIANT_ROOT}/spec/datasets", File.dirname(__FILE__) + '/../../spec/datasets', File.dirname(__FILE__) + '/../datasets')
13
13
  self.datasets_database_dump_path = "#{Rails.root}/tmp/dataset"
14
14
 
15
- # dataset :login_candy
15
+ # dataset :users
16
16
  end
@@ -0,0 +1,81 @@
1
+ module LoginSystem
2
+
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ base.class_eval do
6
+ prepend_before_filter :authenticate_user
7
+ end
8
+ end
9
+
10
+ def authenticate_user
11
+ authenticate_user!
12
+ end
13
+
14
+ def authenticate_user_with_authorize
15
+ if authenticate_user_without_authorize
16
+ action = action_name.to_s.intern
17
+ if user_has_access_to_action?(action)
18
+ true
19
+ else
20
+ permissions = self.class.controller_permissions[action]
21
+ flash[:error] = permissions[:denied_message] || 'You must have moderator privileges to perform this action.'
22
+ respond_to do |format|
23
+ format.html { redirect_to(default_admin_path) }
24
+ format.any(:xml, :json) { head :forbidden }
25
+ end
26
+ false
27
+ end
28
+ else
29
+ redirect_to after_sign_out_path_for(current_user)
30
+ false
31
+ end
32
+ end
33
+ alias_method_chain :authenticate_user, :authorize
34
+
35
+ def user_has_access_to_action?(action)
36
+ result = self.class.user_has_access_to_action?(current_user, action, self)
37
+ end
38
+
39
+ module ClassMethods
40
+ def no_login_required
41
+ # skip_before_filter :authenticate_user
42
+ # Not working in some systems
43
+ end
44
+
45
+ def only_allow_access_to(*args)
46
+ options = {}
47
+ options = args.pop.dup if args.last.kind_of?(Hash)
48
+ options.symbolize_keys!
49
+ actions = args.map { |a| a.to_s.intern }
50
+ actions.each do |action|
51
+ controller_permissions[action] = options
52
+ end
53
+ end
54
+
55
+ def controller_permissions
56
+ @controller_permissions ||= Hash.new { |h,k| h[k.to_s.intern] = Hash.new }
57
+ end
58
+
59
+ def user_has_access_to_action?(user, action, instance=new)
60
+ result = false
61
+
62
+ permissions = controller_permissions[action.to_s.intern]
63
+ case
64
+ when permissions[:when].present?
65
+ allowed_roles = [permissions[:when]].flatten
66
+
67
+ # We no longer have an admin role, if it's in there replace it with administrator
68
+ allowed_roles.map! { |role| role == :admin ? :administrator : role }
69
+
70
+ result = allowed_roles.include? user.class_name.downcase.to_sym
71
+ when permissions[:if].present?
72
+ result = instance.send(permissions[:if])
73
+ else
74
+ result = [:administrator,:designer,:user].include? user.class_name.downcase.to_sym
75
+ end
76
+
77
+ return result
78
+ end
79
+ end
80
+
81
+ end