radiant-users-extension 0.0.5 → 2.1.0.beta

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 (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