adva_user 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +22 -0
  5. data/README +114 -0
  6. data/README.md +29 -0
  7. data/Rakefile +2 -0
  8. data/adva_user.gemspec +17 -0
  9. data/app/controllers/admin/base_account_controller.rb +13 -0
  10. data/app/controllers/admin/users_controller.rb +95 -0
  11. data/app/controllers/password_controller.rb +36 -0
  12. data/app/controllers/session_controller.rb +30 -0
  13. data/app/helpers/users_helper.rb +27 -0
  14. data/app/models/account.rb +7 -0
  15. data/app/models/membership.rb +16 -0
  16. data/app/models/password_mailer.rb +43 -0
  17. data/app/models/user.rb +106 -0
  18. data/app/views/admin/users/_form.html.erb +29 -0
  19. data/app/views/admin/users/_sidebar.html.erb +8 -0
  20. data/app/views/admin/users/edit.html.erb +7 -0
  21. data/app/views/admin/users/index.html.erb +13 -0
  22. data/app/views/admin/users/new.html.erb +5 -0
  23. data/app/views/admin/users/show.html.erb +27 -0
  24. data/app/views/layouts/login.html.erb +24 -0
  25. data/app/views/password/edit.html.erb +14 -0
  26. data/app/views/password/new.html.erb +13 -0
  27. data/app/views/password_mailer/reset_password_email.html.erb +3 -0
  28. data/app/views/password_mailer/updated_password_email.html.erb +1 -0
  29. data/app/views/session/new.html.erb +17 -0
  30. data/config/initializers/menus.rb +25 -0
  31. data/config/routes.rb +14 -0
  32. data/db/migrate/20080402000001_create_users_table.rb +33 -0
  33. data/db/migrate/20080402000005_create_memberships_table.rb +13 -0
  34. data/db/migrate/20090625124502_create_accounts.rb +13 -0
  35. data/db/migrate/20090625133231_add_account_to_user.rb +10 -0
  36. data/lib/action_controller/authenticate_anonymous.rb +70 -0
  37. data/lib/action_controller/authenticate_user.rb +201 -0
  38. data/lib/active_record/belongs_to_author.rb +37 -0
  39. data/lib/adva_user.rb +28 -0
  40. data/lib/adva_user/version.rb +3 -0
  41. data/lib/login/helper_integration.rb +11 -0
  42. data/lib/login/mail_config.rb +39 -0
  43. data/test/contexts.rb +42 -0
  44. data/test/fixtures.rb +18 -0
  45. data/test/functional/admin/users_controller_test.rb +176 -0
  46. data/test/functional/password_controller_test.rb +96 -0
  47. data/test/functional/session_controller_test.rb +1 -0
  48. data/test/functional/user_controller_test.rb +95 -0
  49. data/test/integration/anonymous_login_test.rb +39 -0
  50. data/test/integration/edit_user_test.rb +44 -0
  51. data/test/integration/memberships_test.rb +52 -0
  52. data/test/integration/user_deletion_test.rb +27 -0
  53. data/test/integration/user_login_test.rb +53 -0
  54. data/test/integration/user_login_with_remember_me_test.rb +20 -0
  55. data/test/integration/user_registration_test.rb +64 -0
  56. data/test/test_helper.rb +1 -0
  57. data/test/unit/cells/user_cell_test.rb +13 -0
  58. data/test/unit/helpers/users_helper_test.rb +52 -0
  59. data/test/unit/models/account_test.rb +21 -0
  60. data/test/unit/models/anonymous_test.rb +54 -0
  61. data/test/unit/models/password_mailer_test.rb +26 -0
  62. data/test/unit/models/user_mailer_test.rb +16 -0
  63. data/test/unit/models/user_test.rb +173 -0
  64. data/vendor/gems/authentication/.gitignore +17 -0
  65. data/vendor/gems/authentication/Gemfile +4 -0
  66. data/vendor/gems/authentication/LICENSE +22 -0
  67. data/vendor/gems/authentication/MIT-LICENSE +38 -0
  68. data/vendor/gems/authentication/README +39 -0
  69. data/vendor/gems/authentication/README.md +29 -0
  70. data/vendor/gems/authentication/RUNNING_UNIT_TESTS +13 -0
  71. data/vendor/gems/authentication/Rakefile +61 -0
  72. data/vendor/gems/authentication/authentication.gemspec +17 -0
  73. data/vendor/gems/authentication/lib/authentication.rb +270 -0
  74. data/vendor/gems/authentication/lib/authentication/active_record_extensions.rb +11 -0
  75. data/vendor/gems/authentication/lib/authentication/bogus.rb +13 -0
  76. data/vendor/gems/authentication/lib/authentication/hash_helper.rb +26 -0
  77. data/vendor/gems/authentication/lib/authentication/ldap.rb +49 -0
  78. data/vendor/gems/authentication/lib/authentication/remember_me.rb +52 -0
  79. data/vendor/gems/authentication/lib/authentication/salted_hash.rb +53 -0
  80. data/vendor/gems/authentication/lib/authentication/single_token.rb +53 -0
  81. data/vendor/gems/authentication/lib/authentication/version.rb +3 -0
  82. data/vendor/gems/authentication/lib/radius/dictionary +207 -0
  83. data/vendor/gems/authentication/test_backup/abstract_unit.rb +30 -0
  84. data/vendor/gems/authentication/test_backup/active_record_extension_test.rb +17 -0
  85. data/vendor/gems/authentication/test_backup/authentication_test.rb +231 -0
  86. data/vendor/gems/authentication/test_backup/database.yml +12 -0
  87. data/vendor/gems/authentication/test_backup/fixtures/user.rb +3 -0
  88. data/vendor/gems/authentication/test_backup/fixtures/users.yml +3 -0
  89. data/vendor/gems/authentication/test_backup/options_test.rb +100 -0
  90. data/vendor/gems/authentication/test_backup/remember_me_test.rb +41 -0
  91. data/vendor/gems/authentication/test_backup/salted_hash_test.rb +38 -0
  92. data/vendor/gems/authentication/test_backup/schema.rb +10 -0
  93. data/vendor/gems/authentication/test_backup/single_token_test.rb +44 -0
  94. data/vendor/gems/authentication/test_backup/test_helper.rb +8 -0
  95. metadata +157 -0
@@ -0,0 +1,43 @@
1
+ require "login/mail_config"
2
+
3
+ class PasswordMailer < ActionMailer::Base
4
+ include Login::MailConfig
5
+
6
+ class << self
7
+ def handle_user_password_reset_requested!(event)
8
+ deliver_reset_password_email(
9
+ :user => event.object,
10
+ :from => site(event.source.site).email_from,
11
+ :reset_link => password_reset_link(event.source, event.token),
12
+ :token => event.token
13
+ )
14
+ end
15
+
16
+ def handle_user_password_updated!(event)
17
+ deliver_updated_password_email(
18
+ :user => event.object,
19
+ :from => site(event.source.site).email_from
20
+ )
21
+ end
22
+
23
+ private
24
+
25
+ def password_reset_link(controller, token)
26
+ controller.send(:url_for, :action => 'edit', :token => token)
27
+ end
28
+ end
29
+
30
+ def reset_password_email(attributes = {})
31
+ recipients attributes[:user].email
32
+ from attributes[:from]
33
+ subject I18n.t(:'adva.passwords.notifications.reset_password.subject')
34
+ body attributes
35
+ end
36
+
37
+ def updated_password_email(attributes = {})
38
+ recipients attributes[:user].email
39
+ from attributes[:from]
40
+ subject I18n.t(:'adva.passwords.notifications.password_updated.subject')
41
+ body attributes
42
+ end
43
+ end
@@ -0,0 +1,106 @@
1
+ class User < ActiveRecord::Base
2
+ acts_as_authenticated_user
3
+
4
+ # TODO how do we work this in?
5
+ # acts_as_authenticated_user :token_with => 'Authentication::SingleToken',
6
+ # :authenticate_with => nil
7
+
8
+ scope :verified, -> { where.not(verified_at: nil) }
9
+
10
+ belongs_to :account
11
+ has_many :sites, :through => :memberships
12
+ has_many :memberships, :dependent => :delete_all
13
+
14
+ validates_presence_of :first_name, :email
15
+ validates_uniqueness_of :email # i.e. account attributes are unique per application, not per site
16
+ validates_length_of :first_name, :within => 1..40
17
+ validates_length_of :last_name, :allow_nil => true, :within => 0..40
18
+ validates_format_of :email, :allow_nil => true,
19
+ :with => /(\A(\s*)\Z)|(\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z)/i
20
+
21
+ validates_presence_of :password, :if => :password_required?
22
+ validates_length_of :password, :within => 4..40, :if => :password_required?
23
+
24
+ class << self
25
+ def authenticate(credentials)
26
+ return false unless user = User.find_by_email(credentials[:email])
27
+ user.authenticate(credentials[:password]) ? user : false
28
+ end
29
+
30
+ def anonymous(attributes = {}) # FIXME rename to build_anonymous
31
+ attributes[:anonymous] = true
32
+ new attributes
33
+ end
34
+ end
35
+
36
+ def attributes=(attributes)
37
+ attributes.symbolize_keys!
38
+ memberships = attributes.delete :memberships
39
+ super.tap do
40
+ update_memberships memberships if memberships
41
+ end
42
+ end
43
+
44
+ def update_memberships(memberships)
45
+ memberships.each do |site_id, active|
46
+ site = Site.find(site_id)
47
+ if active
48
+ self.sites << site unless member_of?(site)
49
+ else
50
+ self.sites.delete(site) if member_of?(site)
51
+ end
52
+ end
53
+ end
54
+
55
+ def member_of?(site)
56
+ sites.include?(site)
57
+ end
58
+
59
+ def verified?
60
+ !verified_at.nil?
61
+ end
62
+
63
+ def verify!
64
+ update_attributes :verified_at => Time.zone.now if verified_at.nil?
65
+ end
66
+
67
+ # def restore!
68
+ # update_attributes :deleted_at => nil if deleted_at
69
+ # end
70
+
71
+ def registered?
72
+ !new_record? && !anonymous?
73
+ end
74
+
75
+ def name=(name)
76
+ self.first_name = name
77
+ end
78
+
79
+ def name
80
+ last_name ? "#{first_name} #{last_name}" : first_name
81
+ end
82
+
83
+ def to_s
84
+ name
85
+ end
86
+
87
+ def email_with_name
88
+ "#{name} <#{email}>"
89
+ end
90
+
91
+ def homepage
92
+ return nil unless self[:homepage]
93
+
94
+ self[:homepage][0..6] == 'http://' ? self[:homepage] : 'http://' + self[:homepage]
95
+ end
96
+
97
+ def first_name_from_email
98
+ self.first_name.blank? && self.email ? self.email.split('@').first : self.first_name
99
+ end
100
+
101
+ protected
102
+
103
+ def password_required?
104
+ !anonymous? && (password_hash.nil? || password.present?)
105
+ end
106
+ end
@@ -0,0 +1,29 @@
1
+ <fieldset>
2
+ <div class="col">
3
+ <%= f.text_field :first_name, :label => "First name" %>
4
+ <%= f.text_field :email, :label => "Email" %>
5
+ <%= f.password_field :password, :label => "Password" %>
6
+ </div>
7
+
8
+ <div class="col">
9
+ <%= f.text_field :last_name, :label => "Last name" %>
10
+ <%= f.text_field :homepage, :label => "Homepage" %>
11
+ </div>
12
+ </fieldset>
13
+
14
+ <h4><%= t(:'adva.titles.roles') %></h4>
15
+ <p class="hint text_only"><%= t(:'adva.hints.roles') %></p>
16
+
17
+ <fieldset>
18
+ <% if current_user.has_role?(:superuser) %>
19
+ <p>
20
+ <%= hidden_field_tag "user[roles_attributes][0][selected]", 0 %>
21
+ <span class='hint'><%= t(:'adva.roles.hints.superuser') %></span>
22
+ <%= check_box_tag "user[roles_attributes][0][selected]", 1, @user.has_global_role?(:superuser), :id => "user_role_superuser" %>
23
+ <%= hidden_field_tag "user[roles_attributes][0][name]", 'superuser' %>
24
+ <%= f.label "role_superuser", t(:'adva.roles.labels.superuser'), :class => 'light inline' %>
25
+ </p>
26
+ <% end %>
27
+ </fieldset>
28
+
29
+ <% save_or_cancel_links(f, :cancel_url => admin_site_users_path(@site)) %>
@@ -0,0 +1,8 @@
1
+ <% content_for :sidebar do %>
2
+ <div class="tabs">
3
+ <div class="tab active">
4
+ <%= gravatar_img(@user) %>
5
+ </div>
6
+ </div>
7
+ <% end -%>
8
+
@@ -0,0 +1,7 @@
1
+ <h2><%= t(:'adva.users.titles.edit') %></h2>
2
+
3
+ <%= form_for [:admin, @site, @user] do |f| -%>
4
+ <%= render :partial => 'form', :locals => {:f => f} %>
5
+ <% end -%>
6
+
7
+ <%= render :partial => 'sidebar' %>
@@ -0,0 +1,13 @@
1
+ <ul id="users">
2
+ <% @users.each do |user| %>
3
+ <li>
4
+ <%= gravatar_img(user) %>
5
+ <h4><%= link_to user.name, [:admin, @site, user] %></h4>
6
+ <p><%= user.email %></p>
7
+ <p class="actions">
8
+ <%= link_to t(:'adva.links.edit'), [:edit, :admin, @site, user], :class => 'edit' %>
9
+ <%= link_to t(:'adva.links.delete'), [:admin, @site, user], :class => 'delete', :data => { :confirm => t(:'adva.users.confirm_delete') }, :method => :delete %>
10
+ </p>
11
+ </li>
12
+ <% end %>
13
+ </ul>
@@ -0,0 +1,5 @@
1
+ <h2><%= t(:'adva.users.titles.new') %></h2>
2
+
3
+ <%= form_for [:admin, @site, @user] do |f| -%>
4
+ <%= render :partial => 'form', :locals => {:f => f} %>
5
+ <% end -%>
@@ -0,0 +1,27 @@
1
+ <h2><%= @user.name %></h2>
2
+
3
+ <h3><%= t(:'adva.common.details') %></h3>
4
+ <p>
5
+ <%= t(:'adva.users.labels.email') %>:
6
+ <%= @user.email %>
7
+ </p>
8
+
9
+ <% if @user.homepage %>
10
+ <p>
11
+ <%= t(:'adva.users.labels.url') %>:
12
+ <%= link_to @user.homepage, @user.homepage %>
13
+ </p>
14
+ <% end %>
15
+
16
+ <h3><%= t(:'adva.common.events') %></h3>
17
+ <p>
18
+ <%= t(:'adva.users.labels.created_at') %>:
19
+ <%= @user.created_at %>
20
+ </p>
21
+
22
+ <p>
23
+ <%= t(:'adva.users.labels.updated_at') %>:
24
+ <%= @user.updated_at %>
25
+ </p>
26
+
27
+ <%= render :partial => 'sidebar' %>
@@ -0,0 +1,24 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
5
+ <meta name="generator" content="adva-cms - Open source content management platform" />
6
+ <title>adva-cms: <%= controller.controller_name %></title>
7
+
8
+ <%= stylesheet_link_tag "adva_cms/admin" %>
9
+ <%= javascript_include_tag "adva_cms/application" %>
10
+ <%= yield :head %>
11
+ </head>
12
+ <body>
13
+ <div id="header">
14
+ </div>
15
+
16
+ <div class="main">
17
+ <div id="flashes"><%= render :partial => 'shared/flash' %></div>
18
+ <div id="content">
19
+ <%= yield %>
20
+ </div>
21
+ </div>
22
+
23
+ </body>
24
+ </html>
@@ -0,0 +1,14 @@
1
+ <h2><%= t(:'adva.passwords.titles.edit') %></h2>
2
+
3
+ <p><%= params[:token].blank? ? t(:'adva.passwords.info.please_enter_new_password_and_token') : t(:'adva.passwords.info.please_enter_new_password') %></p>
4
+
5
+ <%= form_for 'user', :url => password_path, :html => { :method => :put } do |f| %>
6
+ <% f.field_set do %>
7
+ <%= label_tag(t(:'adva.passwords.attributes.token')) + text_field_tag('token') unless current_user %>
8
+ <%= f.password_field :password, :label => :"adva.users.attributes.new_password" %>
9
+ <% end %>
10
+
11
+ <% f.buttons do %>
12
+ <%= submit_tag t(:'adva.common.save') %>
13
+ <% end %>
14
+ <% end %>
@@ -0,0 +1,13 @@
1
+ <h2><%= t(:'adva.passwords.titles.new') %></h2>
2
+
3
+ <%= form_tag password_path do %>
4
+ <fieldset>
5
+ <p><%= t(:'adva.passwords.info.please_enter_email_to_reset_password') %></p>
6
+ <%= label_tag 'user[email]', t(:"adva.users.attributes.email") %>
7
+ <%= text_field_tag 'user[email]' %>
8
+ </fieldset>
9
+
10
+ <% buttons do %>
11
+ <%= submit_tag t(:'adva.passwords.links.reset') %>
12
+ <% end %>
13
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <%= t(:'adva.passwords.notifications.reset_password.body', :name => @user.name, :link => @reset_link, :token => @token) %>
2
+
3
+
@@ -0,0 +1 @@
1
+ <%= t(:'adva.passwords.notifications.password_updated.body', :name => @user.name) %>
@@ -0,0 +1,17 @@
1
+ <div id="centered_box">
2
+ <%= form_for @user, :url => session_path, :html => {:id => 'login'} do |f| %>
3
+ <%= hidden_field_tag :return_to, params[:return_to] if params[:return_to] %>
4
+
5
+ <fieldset>
6
+ <%= f.text_field :email, :class => 'big', :label => "Email" %>
7
+ <%= f.password_field :password, :class => 'big', :label => "Password" %>
8
+ <%= check_box_tag 'user[remember_me]', 1, @remember_me, :id => 'user_remember_me' %>
9
+ <%= label_tag :user_remember_me, t(:'adva.session.labels.remember_me'), :class => 'inline light' %>
10
+ </fieldset>
11
+
12
+ <fieldset>
13
+ <%= submit_tag "Login", :id => 'commit' %> <%= t(:'adva.common.connector.or')%>
14
+ <%= link_to t(:'adva.passwords.titles.new'), new_password_path %>
15
+ </fieldset>
16
+ <% end %>
17
+ </div>
@@ -0,0 +1,25 @@
1
+ module Menus
2
+ module Admin
3
+ class Users < Menu::Group
4
+ define do
5
+ id :main
6
+ parent Sites.new.build(scope).find(:users)
7
+
8
+ menu :left, :class => 'left' do
9
+ item :users, :action => :index, :resource => [@site, :user]
10
+ end
11
+ menu :actions, :class => 'actions' do
12
+ activates object.parent.find(:users)
13
+ item :new, :action => :new, :resource => [@site, :user]
14
+ if @user && !@user.new_record?
15
+ item :show, :url => admin_site_user_path(@site, @user)
16
+ item :edit, :url => edit_admin_site_user_path(@site, @user)
17
+ # item :show, :action => :show, :resource => @user
18
+ # item :edit, :action => :edit, :resource => @user
19
+ item :delete, :content => link_to("Delete", [:admin, @site, @user], :method => :delete)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ Rails.application.routes.draw do
2
+ get "login" => "session#new"
3
+ delete "logout" => "session#destroy"
4
+
5
+ resource :session, :controller => "session"
6
+ resource :password, :controller => "password"
7
+
8
+ namespace :admin do
9
+ resources :users
10
+ resources :sites do
11
+ resources :users
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ class CreateUsersTable < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :users do |t|
4
+ t.string :first_name, :limit => 40
5
+ t.string :last_name, :limit => 40
6
+ t.string :email, :limit => 100
7
+ t.string :homepage
8
+ t.string :about
9
+ t.string :signature
10
+
11
+ t.string :password_hash, :limit => 40
12
+ t.string :password_salt, :limit => 40
13
+
14
+ t.string :ip
15
+ t.string :agent
16
+ t.string :referer
17
+
18
+ t.string :remember_me, :limit => 40
19
+ t.string :token_key, :limit => 40
20
+ t.datetime :token_expiration
21
+
22
+ t.boolean :anonymous, :default => false
23
+
24
+ t.timestamps
25
+ t.datetime :verified_at
26
+ t.datetime :deleted_at
27
+ end
28
+ end
29
+
30
+ def self.down
31
+ drop_table :users
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ class CreateMembershipsTable < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :memberships, :force => true do |t|
4
+ t.references :site
5
+ t.references :user
6
+ t.timestamps
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ drop_table :memberships
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ class CreateAccounts < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :accounts do |t|
4
+ t.string :name
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ drop_table :accounts
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ class AddAccountToUser < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :users, :account_id, :integer
4
+ add_index :users, :account_id
5
+ end
6
+
7
+ def self.down
8
+ remove_column :users, :account_id
9
+ end
10
+ end