adva_user 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README +114 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/adva_user.gemspec +17 -0
- data/app/controllers/admin/base_account_controller.rb +13 -0
- data/app/controllers/admin/users_controller.rb +95 -0
- data/app/controllers/password_controller.rb +36 -0
- data/app/controllers/session_controller.rb +30 -0
- data/app/helpers/users_helper.rb +27 -0
- data/app/models/account.rb +7 -0
- data/app/models/membership.rb +16 -0
- data/app/models/password_mailer.rb +43 -0
- data/app/models/user.rb +106 -0
- data/app/views/admin/users/_form.html.erb +29 -0
- data/app/views/admin/users/_sidebar.html.erb +8 -0
- data/app/views/admin/users/edit.html.erb +7 -0
- data/app/views/admin/users/index.html.erb +13 -0
- data/app/views/admin/users/new.html.erb +5 -0
- data/app/views/admin/users/show.html.erb +27 -0
- data/app/views/layouts/login.html.erb +24 -0
- data/app/views/password/edit.html.erb +14 -0
- data/app/views/password/new.html.erb +13 -0
- data/app/views/password_mailer/reset_password_email.html.erb +3 -0
- data/app/views/password_mailer/updated_password_email.html.erb +1 -0
- data/app/views/session/new.html.erb +17 -0
- data/config/initializers/menus.rb +25 -0
- data/config/routes.rb +14 -0
- data/db/migrate/20080402000001_create_users_table.rb +33 -0
- data/db/migrate/20080402000005_create_memberships_table.rb +13 -0
- data/db/migrate/20090625124502_create_accounts.rb +13 -0
- data/db/migrate/20090625133231_add_account_to_user.rb +10 -0
- data/lib/action_controller/authenticate_anonymous.rb +70 -0
- data/lib/action_controller/authenticate_user.rb +201 -0
- data/lib/active_record/belongs_to_author.rb +37 -0
- data/lib/adva_user.rb +28 -0
- data/lib/adva_user/version.rb +3 -0
- data/lib/login/helper_integration.rb +11 -0
- data/lib/login/mail_config.rb +39 -0
- data/test/contexts.rb +42 -0
- data/test/fixtures.rb +18 -0
- data/test/functional/admin/users_controller_test.rb +176 -0
- data/test/functional/password_controller_test.rb +96 -0
- data/test/functional/session_controller_test.rb +1 -0
- data/test/functional/user_controller_test.rb +95 -0
- data/test/integration/anonymous_login_test.rb +39 -0
- data/test/integration/edit_user_test.rb +44 -0
- data/test/integration/memberships_test.rb +52 -0
- data/test/integration/user_deletion_test.rb +27 -0
- data/test/integration/user_login_test.rb +53 -0
- data/test/integration/user_login_with_remember_me_test.rb +20 -0
- data/test/integration/user_registration_test.rb +64 -0
- data/test/test_helper.rb +1 -0
- data/test/unit/cells/user_cell_test.rb +13 -0
- data/test/unit/helpers/users_helper_test.rb +52 -0
- data/test/unit/models/account_test.rb +21 -0
- data/test/unit/models/anonymous_test.rb +54 -0
- data/test/unit/models/password_mailer_test.rb +26 -0
- data/test/unit/models/user_mailer_test.rb +16 -0
- data/test/unit/models/user_test.rb +173 -0
- data/vendor/gems/authentication/.gitignore +17 -0
- data/vendor/gems/authentication/Gemfile +4 -0
- data/vendor/gems/authentication/LICENSE +22 -0
- data/vendor/gems/authentication/MIT-LICENSE +38 -0
- data/vendor/gems/authentication/README +39 -0
- data/vendor/gems/authentication/README.md +29 -0
- data/vendor/gems/authentication/RUNNING_UNIT_TESTS +13 -0
- data/vendor/gems/authentication/Rakefile +61 -0
- data/vendor/gems/authentication/authentication.gemspec +17 -0
- data/vendor/gems/authentication/lib/authentication.rb +270 -0
- data/vendor/gems/authentication/lib/authentication/active_record_extensions.rb +11 -0
- data/vendor/gems/authentication/lib/authentication/bogus.rb +13 -0
- data/vendor/gems/authentication/lib/authentication/hash_helper.rb +26 -0
- data/vendor/gems/authentication/lib/authentication/ldap.rb +49 -0
- data/vendor/gems/authentication/lib/authentication/remember_me.rb +52 -0
- data/vendor/gems/authentication/lib/authentication/salted_hash.rb +53 -0
- data/vendor/gems/authentication/lib/authentication/single_token.rb +53 -0
- data/vendor/gems/authentication/lib/authentication/version.rb +3 -0
- data/vendor/gems/authentication/lib/radius/dictionary +207 -0
- data/vendor/gems/authentication/test_backup/abstract_unit.rb +30 -0
- data/vendor/gems/authentication/test_backup/active_record_extension_test.rb +17 -0
- data/vendor/gems/authentication/test_backup/authentication_test.rb +231 -0
- data/vendor/gems/authentication/test_backup/database.yml +12 -0
- data/vendor/gems/authentication/test_backup/fixtures/user.rb +3 -0
- data/vendor/gems/authentication/test_backup/fixtures/users.yml +3 -0
- data/vendor/gems/authentication/test_backup/options_test.rb +100 -0
- data/vendor/gems/authentication/test_backup/remember_me_test.rb +41 -0
- data/vendor/gems/authentication/test_backup/salted_hash_test.rb +38 -0
- data/vendor/gems/authentication/test_backup/schema.rb +10 -0
- data/vendor/gems/authentication/test_backup/single_token_test.rb +44 -0
- data/vendor/gems/authentication/test_backup/test_helper.rb +8 -0
- 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
|
data/app/models/user.rb
ADDED
@@ -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,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,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 @@
|
|
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
|
data/config/routes.rb
ADDED
@@ -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
|