blue_light_special_heroku_fork 0.2.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. data/LICENSE +20 -0
  2. data/README.rdoc +95 -0
  3. data/Rakefile +95 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/blue_light_special/impersonations_controller.rb +44 -0
  6. data/app/controllers/blue_light_special/passwords_controller.rb +88 -0
  7. data/app/controllers/blue_light_special/sessions_controller.rb +70 -0
  8. data/app/controllers/blue_light_special/users_controller.rb +48 -0
  9. data/app/models/blue_light_special_mailer.rb +19 -0
  10. data/app/models/deliver_change_password_job.rb +19 -0
  11. data/app/models/deliver_welcome_job.rb +17 -0
  12. data/app/models/generic_mailer.rb +22 -0
  13. data/app/models/impersonation.rb +26 -0
  14. data/app/models/mimi_mailer.rb +21 -0
  15. data/app/views/blue_light_special_mailer/change_password.html.erb +9 -0
  16. data/app/views/impersonations/index.html.erb +5 -0
  17. data/app/views/passwords/edit.html.erb +23 -0
  18. data/app/views/passwords/new.html.erb +15 -0
  19. data/app/views/sessions/new.html.erb +48 -0
  20. data/app/views/users/_form.html.erb +21 -0
  21. data/app/views/users/edit.html.erb +6 -0
  22. data/app/views/users/new.html.erb +6 -0
  23. data/app/views/users/show.html.erb +8 -0
  24. data/generators/blue_light_special/USAGE +1 -0
  25. data/generators/blue_light_special/blue_light_special_generator.rb +78 -0
  26. data/generators/blue_light_special/lib/insert_commands.rb +33 -0
  27. data/generators/blue_light_special/lib/rake_commands.rb +22 -0
  28. data/generators/blue_light_special/templates/README +20 -0
  29. data/generators/blue_light_special/templates/application.html.erb +50 -0
  30. data/generators/blue_light_special/templates/blue_light_special.rb +25 -0
  31. data/generators/blue_light_special/templates/blue_light_special.yml +45 -0
  32. data/generators/blue_light_special/templates/factories.rb +23 -0
  33. data/generators/blue_light_special/templates/migrations/create_users.rb +24 -0
  34. data/generators/blue_light_special/templates/migrations/update_users.rb +44 -0
  35. data/generators/blue_light_special/templates/style.css +31 -0
  36. data/generators/blue_light_special/templates/user.rb +3 -0
  37. data/generators/blue_light_special/templates/xd_receiver.html +10 -0
  38. data/generators/blue_light_special/templates/xd_receiver_ssl.html +10 -0
  39. data/generators/blue_light_special_admin/USAGE +1 -0
  40. data/generators/blue_light_special_admin/blue_light_special_admin_generator.rb +30 -0
  41. data/generators/blue_light_special_admin/lib/insert_commands.rb +33 -0
  42. data/generators/blue_light_special_admin/templates/README +16 -0
  43. data/generators/blue_light_special_admin/templates/app/controllers/admin/admin_controller.rb +14 -0
  44. data/generators/blue_light_special_admin/templates/app/controllers/admin/users_controller.rb +52 -0
  45. data/generators/blue_light_special_admin/templates/app/views/admin/users/_form.html.erb +25 -0
  46. data/generators/blue_light_special_admin/templates/app/views/admin/users/edit.html.erb +6 -0
  47. data/generators/blue_light_special_admin/templates/app/views/admin/users/index.html.erb +7 -0
  48. data/generators/blue_light_special_admin/templates/app/views/admin/users/new.html.erb +6 -0
  49. data/generators/blue_light_special_admin/templates/app/views/admin/users/show.html.erb +10 -0
  50. data/generators/blue_light_special_admin/templates/test/integration/admin/users_test.rb +201 -0
  51. data/generators/blue_light_special_tests/USAGE +1 -0
  52. data/generators/blue_light_special_tests/blue_light_special_tests_generator.rb +21 -0
  53. data/generators/blue_light_special_tests/templates/README +58 -0
  54. data/generators/blue_light_special_tests/templates/test/integration/edit_profile_test.rb +35 -0
  55. data/generators/blue_light_special_tests/templates/test/integration/facebook_test.rb +61 -0
  56. data/generators/blue_light_special_tests/templates/test/integration/impersonation_test.rb +39 -0
  57. data/generators/blue_light_special_tests/templates/test/integration/password_reset_test.rb +128 -0
  58. data/generators/blue_light_special_tests/templates/test/integration/sign_in_test.rb +66 -0
  59. data/generators/blue_light_special_tests/templates/test/integration/sign_out_test.rb +28 -0
  60. data/generators/blue_light_special_tests/templates/test/integration/sign_up_test.rb +47 -0
  61. data/lib/blue_light_special.rb +7 -0
  62. data/lib/blue_light_special/authentication.rb +138 -0
  63. data/lib/blue_light_special/configuration.rb +34 -0
  64. data/lib/blue_light_special/extensions/errors.rb +6 -0
  65. data/lib/blue_light_special/extensions/rescue.rb +5 -0
  66. data/lib/blue_light_special/routes.rb +55 -0
  67. data/lib/blue_light_special/user.rb +247 -0
  68. data/rails/init.rb +4 -0
  69. data/shoulda_macros/blue_light_special.rb +244 -0
  70. data/test/controllers/passwords_controller_test.rb +184 -0
  71. data/test/controllers/sessions_controller_test.rb +129 -0
  72. data/test/controllers/users_controller_test.rb +57 -0
  73. data/test/models/blue_light_special_mailer_test.rb +52 -0
  74. data/test/models/impersonation_test.rb +25 -0
  75. data/test/models/user_test.rb +213 -0
  76. data/test/rails_root/app/controllers/accounts_controller.rb +10 -0
  77. data/test/rails_root/app/controllers/application_controller.rb +6 -0
  78. data/test/rails_root/app/helpers/application_helper.rb +5 -0
  79. data/test/rails_root/app/helpers/confirmations_helper.rb +2 -0
  80. data/test/rails_root/app/helpers/passwords_helper.rb +2 -0
  81. data/test/rails_root/config/boot.rb +110 -0
  82. data/test/rails_root/config/environment.rb +22 -0
  83. data/test/rails_root/config/environments/development.rb +19 -0
  84. data/test/rails_root/config/environments/production.rb +1 -0
  85. data/test/rails_root/config/environments/test.rb +37 -0
  86. data/test/rails_root/config/initializers/inflections.rb +10 -0
  87. data/test/rails_root/config/initializers/mime_types.rb +5 -0
  88. data/test/rails_root/config/initializers/requires.rb +13 -0
  89. data/test/rails_root/config/initializers/time_formats.rb +4 -0
  90. data/test/rails_root/config/routes.rb +9 -0
  91. data/test/rails_root/public/dispatch.rb +10 -0
  92. data/test/rails_root/script/create_project.rb +52 -0
  93. data/test/rails_root/test/functional/accounts_controller_test.rb +23 -0
  94. data/test/test_helper.rb +21 -0
  95. metadata +187 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Envy Labs LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,95 @@
1
+ = Blue Light Special
2
+
3
+ Blue Light Special is a derivative from Thoughtbot's
4
+ {Clearance}[http://github.com/thoughtbot/clearance] gem. It's a highly
5
+ opinionated starting point for many of our projects at Envy Labs.
6
+
7
+ In addition to the basic email and password authentication provided by
8
+ Clearance, a default Blue Light Special installation includes:
9
+
10
+ * optional support for authenticating with Facebook Connect, using {mini_fb}[http://github.com/appoxy/mini_fb]
11
+
12
+ * a simple role system with built-in support for admin users
13
+
14
+ * the ability for an admin to impersonate any other user
15
+
16
+ * use of {MadMimi}[http://madmimi.com/r/b8599b9343f82e3bc30984ca4f3fea3f] for sending notification emails
17
+
18
+ * {delayed_job}[http://github.com/tobi/delayed_job] for sending emails in the background
19
+
20
+ * a basic application layout and stylesheet
21
+
22
+ == Setup
23
+
24
+ After installing the Blue Light Special gem, require it in your Rails app and run
25
+ the blue_light_special generator.
26
+
27
+ In your config/environment.rb:
28
+
29
+ config.gem 'blue_light_special'
30
+
31
+ Run the generators and migrate your database:
32
+
33
+ script/generate blue_light_special
34
+ script/generate delayed_job
35
+ rake db:migrate
36
+
37
+ You'll also want to take a look at Blue Light Special's configuration options
38
+ in config/blue_light_special.yml.
39
+
40
+ == Tests
41
+
42
+ Blue Light Special can optionally generate integration tests that cover all
43
+ of its basic features. These tests require {shoulda}[http://github.com/thoughtbot/shoulda],
44
+ {factory_girl}[http://github.com/thoughtbot/factory_girl], {webrat}[http://github.com/brynary/webrat],
45
+ and {fakeweb}[http://github.com/chrisk/fakeweb]. To install the tests:
46
+
47
+ script/generate blue_light_special_tests
48
+
49
+ After the generator runs, you'll see instructions for updating
50
+ test/test_helper.rb to include some helper methods that the tests require.
51
+ You can also use these helper methods in your own integration tests whenever
52
+ you need to sign a user in or out.
53
+
54
+ == Administration Interface
55
+
56
+ The final Blue Light Special generator builds a very simple administration
57
+ interface for your app. This allows admins to manage and impersonate users,
58
+ and it can be used as a starting point for building a more elaborate admin
59
+ interface. If you'd like to generate the admin interface, run:
60
+
61
+ script/generate blue_light_special_admin
62
+
63
+ This will generate your user admin controller and its integration test.
64
+
65
+ == Mad Mimi
66
+
67
+ If you'd like an overview of Mad Mimi, check out the third part of
68
+ {this screencast}[http://railslab.newrelic.com/2009/10/23/episode-21-on-the-edge-part-3].
69
+ In order to get Blue Light Special working with Mad Mimi, you'll need to sign
70
+ up for an account at {madmimi.com}[http://madmimi.com/r/b8599b9343f82e3bc30984ca4f3fea3f].
71
+
72
+ Your Mad Mimi account needs API access, so be sure to enable that during the signup
73
+ process. The support people at Mad Mimi will manually authorize your account for
74
+ API access. This usually happens within a few hours after you've signed up. Until
75
+ your account is authorized, you'll see HTTP errors when your Rails app attempts to
76
+ send email.
77
+
78
+ After you've signed up and your API access has been approved, all you'll need to do is
79
+ put your Mad Mimi username and API key in config/blue_light_special.yml.
80
+
81
+ == Facebook Connect
82
+
83
+ To set up Facebook Connect, go to the {Facebook developer page}[http://facebook.com/developers]
84
+ and create a new Facebook app. Since you're only using this app for Facebook Connect,
85
+ you can leave most of the fields blank. Be sure to give your app a name, and then
86
+ head over to the Connect settings and set the Connect URL to point at your Rails app.
87
+ In the Advanced section, you'll need to set Email Domain to the domain from which you'll
88
+ be sending email messages.
89
+
90
+ After you've finished setting up your Facebook app, grab its API key and secret key
91
+ and put them in config/blue_light_special.yml.
92
+
93
+ == Copyright
94
+
95
+ Copyright (c) 2010 Envy Labs LLC. See LICENSE for details.
@@ -0,0 +1,95 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gem|
8
+ gem.name = "blue_light_special"
9
+ gem.summary = %Q{Rails authentication by email and password}
10
+ gem.description = %Q{Rails authentication by email and password with integrated dependencies to MadMimi. Also provides administrative user impersonation.}
11
+ gem.email = "nate@envylabs.com"
12
+ gem.homepage = "http://github.com/envylabs/blue_light_special"
13
+ gem.authors = ["Nathaniel Bibler", "Mark Kendall", "Caike Souza"]
14
+ gem.files = FileList["[A-Z]*", "{app,config,generators,lib,shoulda_macros,rails}/**/*"]
15
+
16
+ gem.add_dependency "mini_fb", '=0.2.2'
17
+ gem.add_dependency "delayed_job", '=1.8.4'
18
+ gem.add_dependency "mad_mimi_mailer", '=0.0.7'
19
+
20
+ gem.add_development_dependency "shoulda", ">= 0"
21
+ end
22
+ Jeweler::GemcutterTasks.new
23
+ rescue LoadError
24
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
25
+ end
26
+
27
+ namespace :test do
28
+ Rake::TestTask.new(:basic => ["check_dependencies",
29
+ "generator:cleanup",
30
+ "generator:blue_light_special",
31
+ "generator:blue_light_special_tests",
32
+ "generator:blue_light_special_admin"]) do |task|
33
+ task.libs << "lib"
34
+ task.libs << "test"
35
+ task.pattern = "test/{controllers,models}/*_test.rb"
36
+ task.verbose = false
37
+ end
38
+ end
39
+
40
+ generators = %w(blue_light_special blue_light_special_tests blue_light_special_admin)
41
+
42
+ namespace :generator do
43
+ desc "Cleans up the test app before running the generator"
44
+ task :cleanup do
45
+ FileList["test/rails_root/db/**/*"].each do |each|
46
+ FileUtils.rm_rf(each)
47
+ end
48
+
49
+ FileUtils.rm_rf("test/rails_root/vendor/plugins/blue_light_special")
50
+ FileUtils.mkdir_p("test/rails_root/vendor/plugins")
51
+ blue_light_special_root = File.expand_path(File.dirname(__FILE__))
52
+ system("ln -s \"#{blue_light_special_root}\" test/rails_root/vendor/plugins/blue_light_special")
53
+ end
54
+
55
+ desc "Run the blue_light_special generator"
56
+ task :blue_light_special do
57
+ system "cd test/rails_root && ./script/generate blue_light_special -f && ./script/generate delayed_job && rake gems:unpack && rake db:migrate db:test:prepare"
58
+ end
59
+
60
+ desc "Run the blue_light_special tests generator"
61
+ task :blue_light_special_tests do
62
+ system "cd test/rails_root && ./script/generate blue_light_special_tests -f"
63
+ end
64
+
65
+ desc "Run the blue_light_special admin generator"
66
+ task :blue_light_special_admin do
67
+ system "cd test/rails_root && ./script/generate blue_light_special_admin -f"
68
+ end
69
+
70
+ end
71
+
72
+ begin
73
+ require 'rcov/rcovtask'
74
+ Rcov::RcovTask.new do |test|
75
+ test.libs << 'test'
76
+ test.pattern = 'test/**/test_*.rb'
77
+ test.verbose = true
78
+ end
79
+ rescue LoadError
80
+ task :rcov do
81
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
82
+ end
83
+ end
84
+
85
+ task :default => ['test:basic']
86
+
87
+ require 'rake/rdoctask'
88
+ Rake::RDocTask.new do |rdoc|
89
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
90
+
91
+ rdoc.rdoc_dir = 'rdoc'
92
+ rdoc.title = "BlueLightSpecial #{version}"
93
+ rdoc.rdoc_files.include('README*')
94
+ rdoc.rdoc_files.include('lib/**/*.rb')
95
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -0,0 +1,44 @@
1
+ class BlueLightSpecial::ImpersonationsController < ApplicationController
2
+ before_filter :authenticate
3
+ before_filter :check_role, :except => :destroy
4
+
5
+
6
+ def index
7
+ @users = User.all
8
+ render :template => 'impersonations/index'
9
+ end
10
+
11
+ def create
12
+ user = User.find(params[:user_id])
13
+ if user == current_user
14
+ flash[:failure] = "Cannot impersonate yourself"
15
+ redirect_to root_url
16
+ else
17
+ session[:admin_user_id] = current_user.id
18
+ session[:impersonation_hash] = Impersonation.hash_for(current_user.id)
19
+ sign_in(user)
20
+ redirect_to root_url
21
+ end
22
+ end
23
+
24
+ def destroy
25
+ if Impersonation.valid_hash?(session[:admin_user_id], session[:impersonation_hash])
26
+ old_user = current_user
27
+ admin_user = User.find(session[:admin_user_id])
28
+ session[:admin_user_id] = nil
29
+ session[:impersonation_hash] = nil
30
+ sign_in(admin_user)
31
+ redirect_to impersonations_url
32
+ else
33
+ deny_access
34
+ end
35
+ end
36
+
37
+
38
+ private
39
+
40
+
41
+ def check_role
42
+ raise ActionController::Forbidden, "disallowed" unless current_user.admin?
43
+ end
44
+ end
@@ -0,0 +1,88 @@
1
+ class BlueLightSpecial::PasswordsController < ApplicationController
2
+ unloadable
3
+
4
+ skip_before_filter :authenticate, :only => [:new, :create, :edit, :update]
5
+ before_filter :forbid_missing_token, :only => [:edit, :update]
6
+ before_filter :forbid_non_existent_user, :only => [:edit, :update]
7
+ filter_parameter_logging :password, :password_confirmation
8
+
9
+ def new
10
+ render :template => 'passwords/new'
11
+ end
12
+
13
+ def create
14
+ if user = ::User.find_by_email(params[:password][:email])
15
+ user.forgot_password!
16
+ if BlueLightSpecial.configuration.use_delayed_job
17
+ Delayed::Job.enqueue DeliverChangePasswordJob.new(user)
18
+ else
19
+ BlueLightSpecialMailer.deliver_change_password(user)
20
+ end
21
+ flash_notice_after_create
22
+ redirect_to(url_after_create)
23
+ else
24
+ flash_failure_after_create
25
+ render :template => 'passwords/new'
26
+ end
27
+ end
28
+
29
+ def edit
30
+ @user = ::User.find_by_id_and_password_reset_token(
31
+ params[:user_id], params[:token])
32
+ render :template => 'passwords/edit'
33
+ end
34
+
35
+ def update
36
+ @user = ::User.find_by_id_and_password_reset_token(
37
+ params[:user_id], params[:token])
38
+
39
+ if @user.update_password(params[:user][:password],
40
+ params[:user][:password_confirmation])
41
+ sign_in(@user)
42
+ flash_success_after_update
43
+ redirect_to(url_after_update)
44
+ else
45
+ render :template => 'passwords/edit'
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def forbid_missing_token
52
+ if params[:token].blank?
53
+ raise ActionController::Forbidden, "missing token"
54
+ end
55
+ end
56
+
57
+ def forbid_non_existent_user
58
+ unless ::User.find_by_id_and_password_reset_token(
59
+ params[:user_id], params[:token])
60
+ raise ActionController::Forbidden, "non-existent user"
61
+ end
62
+ end
63
+
64
+ def flash_notice_after_create
65
+ flash[:notice] = translate(:deliver_change_password,
66
+ :scope => [:blue_light_special, :controllers, :passwords],
67
+ :default => "You will receive an email within the next few minutes. " <<
68
+ "It contains instructions for changing your password.")
69
+ end
70
+
71
+ def flash_failure_after_create
72
+ flash.now[:failure] = translate(:unknown_email,
73
+ :scope => [:blue_light_special, :controllers, :passwords],
74
+ :default => "Unknown email.")
75
+ end
76
+
77
+ def url_after_create
78
+ sign_in_url
79
+ end
80
+
81
+ def flash_success_after_update
82
+ flash[:success] = translate(:signed_in, :default => "Signed in.")
83
+ end
84
+
85
+ def url_after_update
86
+ '/'
87
+ end
88
+ end
@@ -0,0 +1,70 @@
1
+ class BlueLightSpecial::SessionsController < ApplicationController
2
+ unloadable
3
+
4
+ skip_before_filter :authenticate, :only => [:new, :create, :destroy]
5
+ protect_from_forgery :except => :create
6
+ filter_parameter_logging :password
7
+
8
+ def new
9
+ render :template => 'sessions/new'
10
+ end
11
+
12
+ def create
13
+ @user = if params[:session]
14
+ ::User.authenticate(params[:session][:email], params[:session][:password])
15
+ else
16
+ ::User.find_facebook_user(cookies[BlueLightSpecial.configuration.facebook_api_key + "_session_key"],
17
+ cookies[BlueLightSpecial.configuration.facebook_api_key + "_user"])
18
+ end
19
+
20
+ if @user.nil?
21
+ flash_failure_after_create
22
+ render :template => 'sessions/new', :status => :unauthorized
23
+ else
24
+ sign_in(@user)
25
+ flash_success_after_create
26
+ redirect_back_or(url_after_create)
27
+ end
28
+ end
29
+
30
+ def destroy
31
+ if BlueLightSpecial.configuration.use_facebook_connect
32
+ cookies[BlueLightSpecial.configuration.facebook_api_key + "_user"] = nil
33
+ cookies[BlueLightSpecial.configuration.facebook_api_key + "_session_key"] = nil
34
+ end
35
+ sign_out
36
+ flash_success_after_destroy
37
+ redirect_to(url_after_destroy)
38
+ end
39
+
40
+ private
41
+
42
+ def flash_failure_after_create
43
+ flash.now[:failure] = translate(:bad_email_or_password,
44
+ :scope => [:blue_light_special, :controllers, :sessions],
45
+ :default => "Bad email or password.")
46
+ end
47
+
48
+ def flash_success_after_create
49
+ flash[:success] = translate(:signed_in, :default => "Signed in.")
50
+ end
51
+
52
+ def flash_notice_after_create
53
+ flash[:notice] = translate(:unconfirmed_email,
54
+ :scope => [:blue_light_special, :controllers, :sessions],
55
+ :default => "User has not confirmed email. " <<
56
+ "Confirmation email will be resent.")
57
+ end
58
+
59
+ def url_after_create
60
+ '/'
61
+ end
62
+
63
+ def flash_success_after_destroy
64
+ flash[:success] = translate(:signed_out, :default => "Signed out.")
65
+ end
66
+
67
+ def url_after_destroy
68
+ sign_in_url
69
+ end
70
+ end
@@ -0,0 +1,48 @@
1
+ class BlueLightSpecial::UsersController < ApplicationController
2
+ unloadable
3
+
4
+ skip_before_filter :authenticate, :only => [:new, :create]
5
+ before_filter :redirect_to_root, :only => [:new, :create], :if => :signed_in?
6
+ filter_parameter_logging :password
7
+
8
+ def show
9
+ @user = current_user
10
+ render :template => 'users/show'
11
+ end
12
+
13
+ def new
14
+ @user = ::User.new(params[:user])
15
+ render :template => 'users/new'
16
+ end
17
+
18
+ def create
19
+ @user = ::User.new params[:user]
20
+ if @user.save
21
+ sign_in(@user)
22
+ redirect_to(url_after_create)
23
+ else
24
+ render :template => 'users/new'
25
+ end
26
+ end
27
+
28
+ def edit
29
+ @user = current_user
30
+ render :template => 'users/edit'
31
+ end
32
+
33
+ def update
34
+ @user = current_user
35
+ if @user.update_attributes(params[:user])
36
+ flash[:success] = 'Your profile has been updated.'
37
+ redirect_to user_path(@user)
38
+ else
39
+ render :template => 'users/edit'
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def url_after_create
46
+ root_url
47
+ end
48
+ end