Added a confirmation step to the process of granting and revoking user roles.
authorMatt Amos <zerebubuth@gmail.com>
Mon, 28 Sep 2009 17:35:39 +0000 (17:35 +0000)
committerMatt Amos <zerebubuth@gmail.com>
Mon, 28 Sep 2009 17:35:39 +0000 (17:35 +0000)
app/controllers/user_roles_controller.rb
app/views/user_roles/edit.html.erb [deleted file]
app/views/user_roles/grant.html.erb [new file with mode: 0644]
app/views/user_roles/index.html.erb [deleted file]
app/views/user_roles/new.html.erb [deleted file]
app/views/user_roles/revoke.html.erb [new file with mode: 0644]
app/views/user_roles/show.html.erb [deleted file]
config/locales/en.yml
test/functional/user_roles_controller_test.rb

index b1f24c275432c7e70167169ef68de0624e7f9bea..7e56693df5c4c44ba362183e7717da4f99c7e2ee 100644 (file)
@@ -6,23 +6,35 @@ class UserRolesController < ApplicationController
   before_filter :require_administrator
 
   def grant
-    this_user = User.find_by_display_name(params[:display_name], :conditions => {:visible => true})
-    if this_user and UserRole::ALL_ROLES.include? params[:role]
-      this_user.roles.create(:role => params[:role])
+    # added a random nonce here which isn't predictable, making an CSRF procedure much, much more difficult.
+    if params[:nonce] and params[:nonce] == session[:nonce]
+      this_user = User.find_by_display_name(params[:display_name], :conditions => {:visible => true})
+      if this_user and UserRole::ALL_ROLES.include? params[:role]
+        this_user.roles.create(:role => params[:role])
+        redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
+      else
+        flash[:notice] = t('user_role.grant.fail', :role => params[:role], :name => params[:display_name])
+      end
     else
-      flash[:notice] = t('user_role.grant.fail', :role => params[:role], :name => params[:display_name])
+      @nonce = OAuth::Helper.generate_nonce
+      session[:nonce] = @nonce
     end
-    redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
   end
 
   def revoke
-    this_user = User.find_by_display_name(params[:display_name], :conditions => {:visible => true})
-    if this_user and UserRole::ALL_ROLES.include? params[:role]
-      UserRole.delete_all({:user_id => this_user.id, :role => params[:role]})
+    # added a random nonce here which isn't predictable, making an CSRF procedure much, much more difficult.
+    if params[:nonce] and params[:nonce] == session[:nonce]
+      this_user = User.find_by_display_name(params[:display_name], :conditions => {:visible => true})
+      if this_user and UserRole::ALL_ROLES.include? params[:role]
+        UserRole.delete_all({:user_id => this_user.id, :role => params[:role]})
+        redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
+      else
+        flash[:notice] = t('user_role.revoke.fail', :role => params[:role], :name => params[:display_name])
+      end
     else
-      flash[:notice] = t('user_role.revoke.fail', :role => params[:role], :name => params[:display_name])
+      @nonce = OAuth::Helper.generate_nonce
+      session[:nonce] = @nonce
     end
-    redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
   end
 
   private
diff --git a/app/views/user_roles/edit.html.erb b/app/views/user_roles/edit.html.erb
deleted file mode 100644 (file)
index 609b426..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-<h1>Editing user_role</h1>
-
-<% form_for(@user_role) do |f| %>
-  <%= f.error_messages %>
-
-  <p>
-    <%= f.label :user_id %><br />
-    <%= f.text_field :user_id %>
-  </p>
-  <p>
-    <%= f.label :role %><br />
-    <%= f.text_field :role %>
-  </p>
-  <p>
-    <%= f.submit 'Update' %>
-  </p>
-<% end %>
-
-<%= link_to 'Show', @user_role %> |
-<%= link_to 'Back', user_roles_path %>
\ No newline at end of file
diff --git a/app/views/user_roles/grant.html.erb b/app/views/user_roles/grant.html.erb
new file mode 100644 (file)
index 0000000..ca45266
--- /dev/null
@@ -0,0 +1,5 @@
+<% form_tag request.request_uri do %>
+<%= hidden_field_tag 'nonce', @nonce %>
+<p><%= t('user_role.grant.are_you_sure', :name => params[:display_name], :role => params[:role]) %></p>
+<p><%= submit_tag t'user_role.grant.confirm' %></p>
+<% end %>
diff --git a/app/views/user_roles/index.html.erb b/app/views/user_roles/index.html.erb
deleted file mode 100644 (file)
index e245d68..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-<h1>Listing user_roles</h1>
-
-<table>
-  <tr>
-    <th>User</th>
-    <th>Role</th>
-  </tr>
-
-<% @user_roles.each do |user_role| %>
-  <tr>
-    <td><%=h user_role.user_id %></td>
-    <td><%=h user_role.role %></td>
-    <td><%= link_to 'Show', user_role %></td>
-    <td><%= link_to 'Edit', edit_user_role_path(user_role) %></td>
-    <td><%= link_to 'Destroy', user_role, :confirm => 'Are you sure?', :method => :delete %></td>
-  </tr>
-<% end %>
-</table>
-
-<br />
-
-<%= link_to 'New user_role', new_user_role_path %>
\ No newline at end of file
diff --git a/app/views/user_roles/new.html.erb b/app/views/user_roles/new.html.erb
deleted file mode 100644 (file)
index 0791993..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-<h1>New user_role</h1>
-
-<% form_for(@user_role) do |f| %>
-  <%= f.error_messages %>
-
-  <p>
-    <%= f.label :user_id %><br />
-    <%= f.text_field :user_id %>
-  </p>
-  <p>
-    <%= f.label :role %><br />
-    <%= f.text_field :role %>
-  </p>
-  <p>
-    <%= f.submit 'Create' %>
-  </p>
-<% end %>
-
-<%= link_to 'Back', user_roles_path %>
\ No newline at end of file
diff --git a/app/views/user_roles/revoke.html.erb b/app/views/user_roles/revoke.html.erb
new file mode 100644 (file)
index 0000000..17219d9
--- /dev/null
@@ -0,0 +1,5 @@
+<% form_tag request.request_uri do %>
+<%= hidden_field_tag 'nonce', @nonce %>
+<p><%= t('user_role.revoke.are_you_sure', :name => params[:display_name], :role => params[:role]) %></p>
+<p><%= submit_tag t'user_role.revoke.confirm' %></p>
+<% end %>
diff --git a/app/views/user_roles/show.html.erb b/app/views/user_roles/show.html.erb
deleted file mode 100644 (file)
index 3db11af..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<p>
-  <b>User:</b>
-  <%=h @user_role.user_id %>
-</p>
-
-<p>
-  <b>Role:</b>
-  <%=h @user_role.role %>
-</p>
-
-
-<%= link_to 'Edit', edit_user_role_path(@user_role) %> |
-<%= link_to 'Back', user_roles_path %>
\ No newline at end of file
index 8220a91e925f4edca6368b25e69c13bd1b243b02..5459cd1dae07e511dfb17f1dbaa3532df0960d7c 100644 (file)
@@ -1001,8 +1001,12 @@ en:
       not_a_friend: "{{name}} is not one of your friends."
   user_role:
     grant:
+      are_you_sure: "Are you sure you want to grant the role `{{role}}' to the user `{{name}}'?"
+      confirm: "Confirm"
       fail: "Couldn't grant role `{{role}}' to user `{{name}}'. Please check that the user and role are both valid."
     revoke:
+      are_you_sure: "Are you sure you want to revoke the role `{{role}}' from the user `{{name}}'?"
+      confirm: "Confirm"
       fail: "Couldn't revoke role `{{role}}' from user `{{name}}'. Please check that the user and role are both valid."
   user_block:
     new:
index c2de53934827328039eada4b94f2f3aaa1cf9277..3bced12e4d622056b81d8a53d38e581daa94e2ad 100644 (file)
@@ -4,25 +4,35 @@ class UserRolesControllerTest < ActionController::TestCase
   fixtures :users, :user_roles
 
   test "grant" do
-    check_redirect(:grant, :public_user, "/403.html")
-    check_redirect(:grant, :moderator_user, "/403.html")
-    check_redirect(:grant, :administrator_user, {:controller => :user, :action => :view})
+    check_forbidden(:grant, :public_user)
+    check_forbidden(:grant, :moderator_user)
+    check_success(:grant, :administrator_user)
   end
 
   test "revoke" do
-    check_redirect(:revoke, :public_user, "/403.html")
-    check_redirect(:revoke, :moderator_user, "/403.html")
-    check_redirect(:revoke, :administrator_user, {:controller => :user, :action => :view})
+    check_forbidden(:revoke, :public_user)
+    check_forbidden(:revoke, :moderator_user)
+    check_success(:revoke, :administrator_user)
   end
 
-  def check_redirect(action, user, redirect)
+  def check_forbidden(action, user)
     UserRole::ALL_ROLES.each do |role|
       u = users(user)
       basic_authorization(u.email, "test")
       
       get(action, {:display_name => users(:second_public_user).display_name, :role => role}, {'user' => u.id})
       assert_response :redirect
-      assert_redirected_to redirect
+      assert_redirected_to "/403.html"
+    end
+  end
+
+  def check_success(action, user)
+    UserRole::ALL_ROLES.each do |role|
+      u = users(user)
+      basic_authorization(u.email, "test")
+      
+      get(action, {:display_name => users(:second_public_user).display_name, :role => role}, {'user' => u.id})
+      assert_response :success
     end
   end
 end