adva_user 0.0.1

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 (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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3146f0136b688fa7c5c4f1322192e36870cceba8
4
+ data.tar.gz: 0451a800ba3eabd0a49988c574594fa6694f6d97
5
+ SHA512:
6
+ metadata.gz: 0e562845d0556d547e81c7ba0520dc8b4a3c21cfb067b82b97cf8bbb08fe2f9de374c967752c9af4cc4f3d62670ee769aefabb1178bbf7ce48b4a6e90bb7075f
7
+ data.tar.gz: 698a604a2d145232556e6445d2723e3a5c3cbf82ad100b73d8a0e22ae7f387117b47f40638eaefb24faafdaa2257a319695f2457cfbd5804bb2dba7574c8dc2c
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in adva_user.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Micah Geisel
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,114 @@
1
+ As suggested by the author of this plugin, Bart Duchesne, we've used the
2
+ loginui plugin as a scaffolding and modified it for our own needs.
3
+
4
+ See http://rubyforge.org/projects/loginui/ for more information about this
5
+ fantastic plugin.
6
+
7
+
8
+
9
+
10
+ - original readme file -------------------------------------------------------
11
+
12
+ = Login Plugin
13
+
14
+ Provides a basic user interface for allowing a user to accomplish the
15
+ following tasks:
16
+
17
+ * Login (with Remember Me)
18
+ * Logout
19
+
20
+ * Forgot Password
21
+ * Change Password
22
+
23
+ * Register (with email verification)
24
+ * Delete User
25
+ * Restore Deleted User
26
+
27
+ == Dependencies
28
+
29
+ This plugin is implemented with the help of the "Engine" plugin and
30
+ can either be considered reusable slice of an application or can
31
+ be considered scaffolding to your own login work you will add later
32
+ to your project.
33
+
34
+ This plugin also does not implement the actual authentication process
35
+ itself or even define the "User" object that is authenticated against.
36
+ It just assumes certain functionality is available and any application
37
+ that implements that functionality can use this plugin to provide the
38
+ UI for their authentication.
39
+
40
+ If you do not have your own backend authentication I highly suggest you
41
+ check out the authentication plugin by the same author of this plugin.
42
+ Although not required to go together they do together provide a
43
+ complete authentication system.
44
+
45
+ == Development Status
46
+
47
+ This code has been used on many sites so it is fairly reliable. But all
48
+ the sites it has been used on are very similar in design so some
49
+ aspects that our outside of this design may not be tested as well. For
50
+ example all the sites it is currently used on has email for the username.
51
+ So if you don't use email for username (or don't even have an email
52
+ field) it *should* work but has not received significant testing.
53
+
54
+ Another aspect is Rails 1.x vs. Rails 2.0 apps. This was developed under
55
+ Rails 1.x and 95% of sites using this plugin are on Rails 1.x. But it
56
+ has been taken to Rails 2.0 and seems to work well there.
57
+
58
+ I welcome patches towards making this plugin work in different
59
+ environments.
60
+
61
+ == Your User model
62
+
63
+ Regardless of if you use the authentication plugin or build your own
64
+ you will need a user model that this plugin assumes. The user model
65
+ must be named "User". Also your User model needs a field that can
66
+ serve as the username. "email" is prefered (because people can
67
+ remember that) but username and user_name will also be accepted. If
68
+ you have something completely different then implement a class method
69
+ on the user object called "username_field" this method should return
70
+ whatever field is being used as your username.
71
+
72
+ == Optional support
73
+
74
+ The email notifications will only be sent if a "email" field is
75
+ on the model. This is regardless of what you use for a username. There
76
+ is currently no way to disable email notifications if you have the
77
+ email field. Obviously the "forgot my password" feature will not work
78
+ without an email field on the User model as well.
79
+
80
+ == Providing your own authentication
81
+
82
+ If you want to provide your own authentication system instead of using
83
+ the authentication plugin you will need to implement the following
84
+ actions on your User model.
85
+
86
+ === Required methods
87
+
88
+ password=:: Will assign the model a new password
89
+ assign_token(name, expiration=nil)::
90
+ Will return a token that can be used to authenticate the user with.
91
+ This is used for URL token authentication (in email confirmation,
92
+ forgot password and restore deleted user) and also used in the
93
+ "Remember Me" authentication. The expiration can be considered
94
+ optional.
95
+ authenticate(password)::
96
+ Will authenticate the current user against the given password
97
+ returning true or false to indicate the success
98
+
99
+ === Optional methods
100
+
101
+ password_confirmation=::
102
+ Not required but if the model responds to this method then it
103
+ will receive a copy of the password when a user is updating
104
+ their password for verification purposes.
105
+ deleted_at and deleted_at=::
106
+ If the model responds to deleted_at and deleted_at then when
107
+ a user is removed it will just get a date/time value to indicate
108
+ the user has been removed. It will assume once a object has this
109
+ value it will not be found unless User.find_with_deleted is used.
110
+ This is compatible with acts_as_paraniod
111
+ User.find_with_deleted(*find_args)::
112
+ If the User class responds to then then this will be called when
113
+ attempting to restore a user. This is for compatibility with
114
+ acts_as_paranoid and anything else implementing that interface.
@@ -0,0 +1,29 @@
1
+ # AdvaUser
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'adva_user'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install adva_user
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/adva_user/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Micah Geisel"]
6
+ gem.email = ["micah@botandrose.com"]
7
+ gem.description = %q{Adva User}
8
+ gem.summary = %q{Engine for Adva CMS user accounts}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "adva_user"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = AdvaUser::VERSION
17
+ end
@@ -0,0 +1,13 @@
1
+ class Admin::BaseAccountController < Admin::BaseController
2
+ before_filter :set_account
3
+
4
+ def set_account
5
+ @account = current_user.account
6
+ end
7
+
8
+ def require_authentication
9
+ unless current_user and current_user.account
10
+ return redirect_to_login(t(:'adva.flash.authentication_required'))
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,95 @@
1
+ class Admin::UsersController < Admin::BaseController
2
+ before_filter :set_users, :only => [:index]
3
+ before_filter :set_user, :only => [:show, :edit, :update, :destroy]
4
+ before_filter :authorize_access
5
+ before_filter :authorize_params, :only => :update
6
+
7
+ # guards_permissions :user
8
+
9
+ def index
10
+ end
11
+
12
+ def show
13
+ end
14
+
15
+ def new
16
+ @user = User.new
17
+ end
18
+
19
+ def create
20
+ # yuck! rails' params parsing is broken
21
+ params[:user][:roles_attributes] = params[:user][:roles_attributes].map { |key, value| value } if params[:user][:roles_attributes]
22
+
23
+ @user = User.new(params[:user])
24
+ @user.memberships.build(:site => @site) if @site and !@user.has_role?(:superuser)
25
+
26
+ if @user.save
27
+ @user.verify! # TODO hu??
28
+ trigger_events(@user)
29
+ flash[:notice] = t(:'adva.users.flash.create.success')
30
+ redirect_to admin_user_url(@site, @user)
31
+ else
32
+ flash.now[:error] = t(:'adva.users.flash.create.failure')
33
+ render :action => :new
34
+ end
35
+ end
36
+
37
+ def edit
38
+ end
39
+
40
+ def update
41
+ # yuck! rails' params parsing is broken
42
+ params[:user][:roles_attributes] = params[:user][:roles_attributes].map { |key, value| value } if params[:user][:roles_attributes]
43
+
44
+ if @user.update_attributes(params[:user])
45
+ trigger_events(@user)
46
+ flash[:notice] = t(:'adva.users.flash.update.success')
47
+ redirect_to admin_user_url(@site, @user)
48
+ else
49
+ flash.now[:error] = t(:'adva.users.flash.update.failure')
50
+ render :action => :edit
51
+ end
52
+ end
53
+
54
+ def destroy
55
+ if @user.destroy
56
+ trigger_events(@user)
57
+ flash[:notice] = t(:'adva.users.flash.destroy.success')
58
+ redirect_to admin_users_url(@site)
59
+ else
60
+ flash.now[:error] = t(:'adva.users.flash.destroy.failure')
61
+ render :action => :edit
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def set_menu
68
+ @menu = Menus::Admin::Users.new
69
+ end
70
+
71
+ def set_users
72
+ @users = @site ? @site.users_and_superusers :
73
+ User.admins_and_superusers
74
+ end
75
+
76
+ def set_user
77
+ @user = User.find(params[:id])
78
+ end
79
+
80
+ # FIXME extract this and use Rbac contexts instead
81
+ def authorize_access
82
+ redirect_to admin_sites_url unless @site || current_user.has_role?(:superuser)
83
+ end
84
+
85
+ def authorize_params
86
+ return
87
+ return unless params[:user] && params[:user][:roles]
88
+
89
+ if params[:user][:roles].has_key?('superuser') && !current_user.has_role?(:superuser) ||
90
+ params[:user][:roles].has_key?('admin') && !current_user.has_role?(:admin, @site)
91
+ raise "unauthorized parameter" # TODO raise something more meaningful
92
+ end
93
+ # TODO as well check for membership site_id if !user.has_role?(:superuser)
94
+ end
95
+ end
@@ -0,0 +1,36 @@
1
+ class PasswordController < BaseController
2
+ renders_with_error_proc :below_field
3
+ layout 'login'
4
+
5
+ def new
6
+ end
7
+
8
+ def create
9
+ flash[:notice] = t(:'adva.passwords.flash.create.notification')
10
+ if user = User.find_by_email(params[:user][:email])
11
+ token = user.assign_token 'password'
12
+ user.save!
13
+ trigger_event user, :password_reset_requested, :token => "#{user.id};#{token}"
14
+ redirect_to edit_password_url
15
+ else
16
+ render :action => :new
17
+ end
18
+ end
19
+
20
+ def edit
21
+ params[:token] = nil unless current_user # TODO: maybe solve this nicer?
22
+ end
23
+
24
+ def update
25
+ if current_user && current_user.update_attributes(params[:user].slice(:password))
26
+ trigger_event current_user, :password_updated
27
+ flash[:notice] = t(:'adva.passwords.flash.update.success')
28
+ authenticate_user(:email => current_user.email, :password => params[:user][:password])
29
+ redirect_to root_url
30
+ else
31
+ params[:token] = nil # ugh
32
+ flash[:error] = t(:'adva.passwords.flash.update.failure')
33
+ render :action => :edit
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,30 @@
1
+ class SessionController < BaseController
2
+ renders_with_error_proc :below_field
3
+
4
+ skip_before_filter :verify_authenticity_token # disable forgery protection
5
+
6
+ layout 'login'
7
+
8
+ def new
9
+ @user = User.new
10
+ end
11
+
12
+ def create
13
+ if authenticate_user(params[:user])
14
+ remember_me! if params[:user][:remember_me]
15
+ flash[:notice] = t(:'adva.session.flash.create.success')
16
+ redirect_to return_from(:login)
17
+ else
18
+ @user = User.new(:email => params[:user][:email])
19
+ @remember_me = params[:user][:remember_me]
20
+ flash.now[:error] = t(:'adva.session.flash.create.failure')
21
+ render :action => 'new'
22
+ end
23
+ end
24
+
25
+ def destroy
26
+ logout
27
+ flash[:notice] = t(:'adva.session.flash.destroy.success')
28
+ redirect_to return_from(:logout)
29
+ end
30
+ end
@@ -0,0 +1,27 @@
1
+ module UsersHelper
2
+ def who(name)
3
+ name = name.name if name.is_a? User
4
+ return current_user && current_user.name == name ? t(:'adva.common.you') : name
5
+ end
6
+
7
+ def gravatar_img(user, options = {})
8
+ image_tag gravatar_url(user.email), {:class => 'avatar'}.merge(options)
9
+ end
10
+
11
+ def gravatar_url(email = nil, size = 80)
12
+ default = '/assets/adva_cms/avatar.gif'
13
+ return default if email.blank?
14
+ require 'digest/md5'
15
+ digest = Digest::MD5.hexdigest(email)
16
+ # TODO #{ActionController::AbstractRequest.relative_url_root} missing in Rails 2.2
17
+ "http://www.gravatar.com/avatar.php?size=#{size}&gravatar_id=#{digest}&default=http://#{request.host_with_port}/assets/adva_cms/avatar.gif"
18
+ end
19
+
20
+ def link_to_author resource, options = {}
21
+ include_email = options[:include_email] && resource.respond_to?(:author_email)
22
+ name = resource.author_name
23
+ text = resource.author_homepage.blank? ? name : link_to(h(name), h(resource.author_homepage))
24
+ text = "#{text} (#{resource.author_email})" if include_email
25
+ text.html_safe
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ class Account < ActiveRecord::Base
2
+ has_many :users
3
+
4
+ def members
5
+
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ class Membership < ActiveRecord::Base
2
+ belongs_to :site
3
+ belongs_to :user
4
+
5
+ validates_uniqueness_of :site_id, :scope => :user_id
6
+
7
+ # tentacle does this. is it a good idea to keep has_many :roles on the membership?
8
+ # before_create :set_first_user_admin
9
+ # def set_first_user_admin
10
+ # self.transaction do
11
+ # if group && group.members.count == 0
12
+ # self.admin = true
13
+ # end
14
+ # end
15
+ # end
16
+ end