I constructed a Many-to-Many association between Users and Roles.
When a non-administrator logs in, I have hidden the Edit Role function, using
using the following code:
view/users/edit.html.erb
<%= error_messages_for :user %>
<% form_for @user do |f| -%>
<p><label for="login">Login</label><br/>
<%= f.text_field :login %></p>
<p><label for="email">Email</label><br/>
<%= f.text_field :email %></p>
<p><label for="password">Password</label><br/>
<%= f.password_field :password %></p>
<p><label for="password_confirmation">Confirm Password</label><br/>
<%= f.password_field :password_confirmation %></p>
<% if admin? %>
<% for role in Role.find(:all) %>
<div>
<%= check_box_tag "user[role_ids][]", role.id, @user.roles.include?(role) %>
<%= role.name %>
</div>
<% end %>
<% else %>
<% hidden_field :email, :email %>
<% end %>
<p><%= submit_tag 'Update' %></p>
<% end %>
the terminal output, was what I expected and is as follows:
Processing UsersController#update (for 127.0.0.1 at 2010-01-05 21:28:54) [PUT]
Parameters: {"commit"=>"Update", "action"=>"update", "_method"=>"put", "authenticity_token"=>"E6qUNM3gS9OmxuAZpmF7FE2Mr/lowznNLMd6ENNT6uk=", "id"=>"5", "controller"=>"users", "user"=>{"password_confirmation"=>"[FILTERED]", "password"=>"[FILTERED]", "login"=>"lesa", "email"=>"[email protected]"}}
However when I was surprised the user lost her rights (prior to her password update her roles: [1,2])
>> user = User.find_by_login("lesa")
=> #<User id: 5, login: "lesa", email: "[email protected]", crypted_password: "58026ae120d0686196df3c72c9e3df5da596326d", salt: "f02ef9e00d16f1b9f82dfcc488fdf96bf5aab4a8", created_at: "2009-12-29 15:15:51", updated_at: "2010-01-05 21:28:54", remember_token: nil, remember_token_expires_at: nil>
>> user.role_ids
=> []
>>
In the user model controller I am using:
attr_accessible :login, :email, :password, :password_confirmation, :role_ids
How would it be possible for users without the proper rights (role) to NOT update their role_ids? Obviously what I have is seriously flawed. Below is the terminal output of an Administrator correcting Lesa's Rights (role).
Processing UsersController#update (for 127.0.0.1 at 2010-01-05 21:34:01) [PUT]
Parameters: {"commit"=>"Update", "action"=>"update", "_method"=>"put", "authenticity_token"=>"/yC1s9T8yWZH+eM5fnhPwdeHPCTcT1d8IGoIn+tEd4Q=", "id"=>"5", "controller"=>"users", "user"=>{"password_confirmation"=>"[FILTERED]", "role_ids"=>["2"], "password"=>"[FILTERED]", "login"=>"lesa", "email"=>"[email protected]"}}
User controller code:
class UsersController < ApplicationController
# Be sure to include AuthenticationSystem in Application Controller instead
#routine that is excecuted before every action in controller "Before_filter
before_filter :login_required
require_role "admin", :for => [:index, :create, :destroy]
def index
@users = User.find(:all)
end
def show
@user = User.find(params[:id])
end
def destroy
@user = User.find(params[:id])
@user.destroy
redirect_to(users_url)
end
def edit
@user = User.find(params[:id])
end
def update
@user = User.find(params[:id])
params[:user][:role_ids] ||= []
if @user.update_attributes(params[:user])
flash[:notice] = 'User was successfully updated.'
redirect_to(user_path(@user))
else
render :action => 'edit'
end
end
# render new.rhtml
def new
end
def create
cookies.delete :auth_token
# protects against session fixation attacks, wreaks havoc with
# request forgery protection.
# uncomment at your own risk
# reset_session
@user = User.new(params[:user])
@user.save
if @user.errors.empty?
self.current_user = @user
redirect_back_or_default('/')
flash[:notice] = "Thanks for signing up!"
else
render :action => 'new'
end
end
end