Made the Users Controller RESTful. This obviated the need for the currently functionality of the AdminController, so I removed it and consolidated tests.

git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@409 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
lukemelia 2007-01-26 06:37:44 +00:00
parent 707b8cdf86
commit 109a1847fb
21 changed files with 110 additions and 130 deletions

View file

@ -1,49 +0,0 @@
class AdminController < ApplicationController
before_filter :admin_login_required
def index
@user_pages, @users = paginate :users, :order => 'login ASC', :per_page => 10
@total_users = User.find(:all).size
# When we call login/signup from the admin page
# we store the URL so that we get returned here when signup is successful
store_location
end
def destroy
@deleted_user = User.find_by_id(params[:id])
@saved = @deleted_user.destroy
@total_users = User.find(:all).size
respond_to do |wants|
wants.html do
if @saved
notify :notice, "Successfully deleted user #{@deleted_user.login}", 2.0
redirect_to :action => 'index'
else
notify :error, "Failed to delete user #{@deleted_user.login}", 2.0
redirect_to :action => 'index'
end
end
wants.js do
render
end
wants.xml { render :text => '200 OK. User deleted.', :status => 200 }
end
end
protected
def admin_login_required
unless User.find_by_id_and_is_admin(session['user_id'], true)
notify :error, "Only admin users are allowed access to this function"
redirect_to home_path
return false
end
end
end

View file

@ -62,6 +62,15 @@ class ApplicationController < ActionController::Base
end
end
protected
def admin_login_required
unless User.find_by_id_and_is_admin(session['user_id'], true)
render :text => "401 Unauthorized: Only admin users are allowed access to this function.", :status => 401
return false
end
end
private
def parse_date_per_user_prefs( s )

View file

@ -1,19 +1,29 @@
class UserController < ApplicationController
class UsersController < ApplicationController
if Tracks::Config.auth_schemes.include?('open_id')
open_id_consumer
before_filter :begin_open_id_auth, :only => :update_auth_type
end
before_filter :admin_login_required, :only => [ :index, :create, :destroy ]
verify :method => :post,
:only => %w( create ),
:render => { :text => '403 Forbidden: Only POST requests on this resource are allowed.',
:status => 403 }
def index
@user_pages, @users = paginate :users, :order => 'login ASC', :per_page => 10
@total_users = User.find(:all).size
# When we call login/signup from the admin page
# we store the URL so that we get returned here when signup is successful
store_location
end
# verify :method => :post,
# :only => %w( create ),
# :render => { :text => '403 Forbidden: Only POST requests on this resource are allowed.',
# :status => 403 }
# Example usage: curl -H 'Accept: application/xml' -H 'Content-Type: application/xml'
# -u admin:up2n0g00d
# -d '<request><login>username</login><password>abc123</password></request>'
# http://our.tracks.host/user/create
# http://our.tracks.host/users
#
def create
if params['exception']
@ -38,6 +48,33 @@ class UserController < ApplicationController
render_failure user.errors.to_xml
end
end
def destroy
@deleted_user = User.find_by_id(params[:id])
@saved = @deleted_user.destroy
@total_users = User.find(:all).size
respond_to do |wants|
wants.html do
if @saved
notify :notice, "Successfully deleted user #{@deleted_user.login}", 2.0
redirect_to :action => 'index'
else
notify :error, "Failed to delete user #{@deleted_user.login}", 2.0
redirect_to :action => 'index'
end
end
wants.js do
render
end
wants.xml { render :text => '200 OK. User deleted.', :status => 200 }
end
end
def change_password
@page_title = "TRACKS::Change password"
@ -47,7 +84,7 @@ class UserController < ApplicationController
if do_change_password_for(@user)
redirect_to :controller => 'preferences'
else
redirect_to :controller => 'user', :action => 'change_password'
redirect_to :action => 'change_password'
notify :warning, "There was a problem saving the password. Please retry."
end
end
@ -77,7 +114,7 @@ class UserController < ApplicationController
redirect_to :controller => 'preferences'
else
notify :warning, "There was a problem updating your authentication type: #{ @user.errors.full_messages.join(', ')}"
redirect_to :controller => 'user', :action => 'change_auth_type'
redirect_to :action => 'change_auth_type'
end
end
@ -121,7 +158,7 @@ class UserController < ApplicationController
@user.crypt_word
@user.save
notify :notice, "New token successfully generated"
redirect_to :controller => 'user', :action => 'preferences'
redirect_to :controller => 'preferences', :action => 'index'
end
protected

View file

@ -1,2 +0,0 @@
module AdminHelper
end

View file

@ -1,6 +1,6 @@
module TodosHelper
require 'user_controller'
require 'users_controller'
# Counts the number of uncompleted items in the specified context
#
def count_items(context)

View file

@ -1,2 +0,0 @@
<h1>Admin#create</h1>
<p>Find me in app/views/admin/create.rhtml</p>

View file

@ -1 +0,0 @@
page.notify :error, @error_message || "An error occurred on the server.", 8.0

View file

@ -1,2 +0,0 @@
<h1>Admin#update</h1>
<p>Find me in app/views/admin/update.rhtml</p>

View file

@ -49,7 +49,7 @@
<li><%= navigation_link( "Preferences", {:controller => "preferences", :action => "index"}, {:accesskey => "u", :title => "Show my preferences"} ) %></li>
<li><%= navigation_link( "Import/Export", {:controller => "data", :action => "index"}, {:accesskey => "i", :title => "Import and export data"} ) %></li>
<% if @user.is_admin? -%>
<li><%= navigation_link("Admin", {:controller => "admin", :action => "index"}, {:accesskey => "a", :title => "Add or delete users"} ) %></li>
<li><%= navigation_link("Admin", users_path, {:accesskey => "a", :title => "Add or delete users"} ) %></li>
<% end -%>
<li><%= navigation_link(image_tag("feed-icon.png", :size => "16X16", :border => 0), {:controller => "feedlist", :action => "index"}, :title => "See a list of available feeds" ) %></li>
</ul>

View file

@ -35,7 +35,7 @@
<div class="description">Token (for feeds and API use):</div>
<div id="token><span class="highlight"><%= @user.word %></span></div>
<div class="token_regenerate">
<%= button_to "Generate a new token", { :controller => 'user', :action => 'refresh_token'},
<%= button_to "Generate a new token", refresh_token_user_path(@user),
:confirm => "Are you sure? Generating a new token will replace the existing one and break any external usages of this token." %>
</div>
</div>
@ -44,18 +44,18 @@
<% if Tracks::Config.auth_schemes.length > 1 %>
<p>Your authentication type is <span class="highlight"><%= @user.auth_type %></span>.
<div class="actions">
<%= link_to "Change your authentication type &raquo;", { :controller => 'user', :action => 'change_auth_type'}, :class => 'edit_link' %>
<%= link_to "Change your authentication type &raquo;", change_auth_type_user_path(@user), :class => 'edit_link' %>
</div>
<% end %>
<% if @user.auth_type == 'database' %>
<div class="actions">
<%= link_to 'Change your password &raquo;', :controller => 'user', :action => 'change_password' %>
<%= link_to 'Change your password &raquo;', change_password_user_path(@user) %>
</div>
<% end %>
<% if @user.auth_type == 'open_id' %>
<p>Your Open ID URL is <span class="highlight"><%= @user.open_id_url %></span>.
<div class="actions">
<%= link_to 'Change Your Identity URL &raquo;', :controller => 'user', :action => 'change_auth_type' %></p>
<%= link_to 'Change Your Identity URL &raquo;', change_auth_type_user_path(@user) %></p>
</div>
<% end %>
</div>

View file

@ -24,7 +24,7 @@
<td><%= h user.contexts.size %></td>
<td><%= h user.projects.size %></td>
<td><%= h user.notes.size %></td>
<td><%= !user.is_admin? ? link_to_remote( image_tag("blank.png", :title =>"Destroy user", :class=>"delete_item"), {:url => { :controller => 'admin', :action => 'destroy', :id => user.id }, :confirm => "Warning: this will delete user \'#{user.login}\', all their actions, contexts, project and notes. Are you sure that you want to continue?" }, { :class => "icon" } ) : "&nbsp;" %></td>
<td><%= !user.is_admin? ? link_to_remote( image_tag("blank.png", :title =>"Destroy user", :class=>"delete_item"), {:url => user_path(user), :method => :delete, :confirm => "Warning: this will delete user \'#{user.login}\', all their actions, contexts, project and notes. Are you sure that you want to continue?" }, { :class => "icon" } ) : "&nbsp;" %></td>
</tr>
<% end %>
</table>

View file

@ -14,11 +14,6 @@ ActionController::Routing::Routes.draw do |map|
# instead of a file named 'wsdl'
#map.connect ':controller/service.wsdl', :action => 'wsdl'
# Admin Routes
map.connect 'admin', :controller => 'admin', :action => 'index'
map.connect 'admin/destroy/:id', :controller => 'admin', :action => 'destroy', :requirements => {:id => /\d+/}
# Mobile/lite version
map.connect 'mobile', :controller => 'mobile', :action => 'index'
map.connect 'mobile/add_action', :controller => 'mobile', :action => 'show_add_form'
@ -28,6 +23,11 @@ ActionController::Routing::Routes.draw do |map|
map.connect 'logout', :controller => 'login', :action => 'logout'
map.connect 'signup', :controller => 'login', :action => 'signup'
map.resources :users,
:member => {:change_password => :get, :update_password => :post,
:change_auth_type => :get, :update_auth_type => :post,
:refresh_token => :post }
# ToDo Routes
map.resources :todos,
:member => {:toggle_check => :post},

View file

@ -80,7 +80,7 @@
<ul>
<li>In a browser (if you haven't loaded the example data), go to <code>http://0.0.0.0:3000/signup</code>. This will allow you to choose a username and password for the admin user. Thereafter, anyone else trying to access <code>/signup</code> will get a message that they are not allowed to sign up, and are given your email address to contact for permission. When you are logged in as the admin user, you can visit <code>/signup</code> to sign up additional users (who will not be able to view any of your next actions, contexts, projects or notes, but can set up their own separate tasks), and visit <code>/login</code> to login yourself.</li>
<li>Add some contexts at <code>http://0.0.0.0:3000/contexts</code> (you must do this before adding any next actions) and projects at <code>http://0.0.0.0:3000/projects</code> and then you're ready to add all your next actions.</li>
<li>You can set various preferences by visiting <code>http://0.0.0.0:3000/user/preferences</code>. These are stored on a per-user basis in the database.</li>
<li>You can set various preferences by visiting <code>http://0.0.0.0:3000/users/preferences</code>. These are stored on a per-user basis in the database.</li>
<li>Have fun!</li>
</ul>

View file

@ -1,41 +0,0 @@
require File.dirname(__FILE__) + '/../test_helper'
require 'admin_controller'
# Re-raise errors caught by the controller.
class AdminController; def rescue_action(e) raise e end; end
class AdminControllerTest < Test::Unit::TestCase
fixtures :users, :preferences, :projects, :contexts, :todos
def setup
@controller = AdminController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end
def test_get_index_when_not_logged_in
get :index
assert_redirected_to :controller => 'login', :action => 'login'
end
def test_get_index_by_nonadmin
@request.session['user_id'] = users(:other_user).id
get :index
assert_redirected_to home_path
end
def test_get_index_by_admin
@request.session['user_id'] = users(:admin_user).id
get :index
assert_response :success
end
def test_destroy_user
@no_users_before = User.find(:all).size
@request.session['user_id'] = users(:admin_user).id
xhr :post, :destroy, :id => 3
assert_rjs :page, "user-3", :remove
assert_equal @no_users_before-1, User.find(:all).size
end
end

View file

@ -1,21 +1,46 @@
require File.dirname(__FILE__) + '/../test_helper'
require 'user_controller'
require 'users_controller'
require 'user'
# Re-raise errors caught by the controller.
class UserController; def rescue_action(e) raise e end; end
class UsersController; def rescue_action(e) raise e end; end
class UserControllerTest < Test::Unit::TestCase
class UsersControllerTest < Test::Unit::TestCase
fixtures :users
def setup
assert_equal "test", ENV['RAILS_ENV']
assert_equal "change-me", Tracks::Config.salt
@controller = UserController.new
@controller = UsersController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end
def test_get_index_when_not_logged_in
get :index
assert_redirected_to :controller => 'login', :action => 'login'
end
def test_get_index_by_nonadmin
@request.session['user_id'] = users(:other_user).id
get :index
assert_redirected_to home_path
end
def test_get_index_by_admin
@request.session['user_id'] = users(:admin_user).id
get :index
assert_response :success
end
def test_destroy_user
@no_users_before = User.find(:all).size
@request.session['user_id'] = users(:admin_user).id
xhr :post, :destroy, :id => 3
assert_rjs :page, "user-3", :remove
assert_equal @no_users_before-1, User.find(:all).size
end
def test_update_password_successful
get :change_password # should fail because no login
assert_redirected_to :controller => 'login', :action => 'login'
@ -36,7 +61,7 @@ class UserControllerTest < Test::Unit::TestCase
assert_redirected_to :controller => 'login', :action => 'login'
@request.session['user_id'] = users(:admin_user).id # log in the admin user
post :update_password, :updateuser => {:password => 'newpassword', :password_confirmation => 'wrong'}
assert_redirected_to :controller => 'user', :action => 'change_password'
assert_redirected_to :controller => 'users', :action => 'change_password'
assert users(:admin_user).save, false
assert_equal flash[:warning], 'There was a problem saving the password. Please retry.'
end
@ -46,7 +71,7 @@ class UserControllerTest < Test::Unit::TestCase
assert_redirected_to :controller => 'login', :action => 'login'
@request.session['user_id'] = users(:admin_user).id # log in the admin user
post :update_password, :updateuser => {:password => 'ba', :password_confirmation => 'ba'}
assert_redirected_to :controller => 'user', :action => 'change_password'
assert_redirected_to :controller => 'users', :action => 'change_password'
assert users(:admin_user).save, false
# For some reason, no errors are being raised now.
#assert_equal 1, users(:admin_user).errors.count

View file

@ -1,8 +1,8 @@
require File.dirname(__FILE__) + '/../test_helper'
require 'user_controller'
require 'users_controller'
# Re-raise errors caught by the controller.
class UserController; def rescue_action(e) raise e end; end
class UsersController; def rescue_action(e) raise e end; end
class CreateUserControllerTest < ActionController::IntegrationTest
fixtures :users
@ -21,7 +21,7 @@ class CreateUserControllerTest < ActionController::IntegrationTest
def test_fails_with_401_if_not_admin_user
authenticated_post_xml_to_user_create @@foobar_postdata, users(:other_user).login, 'sesame'
assert_401_unauthorized
assert_401_unauthorized_admin
end
def test_content_type_must_be_xml
@ -71,13 +71,13 @@ class CreateUserControllerTest < ActionController::IntegrationTest
end
def test_fails_with_get_verb
authenticated_get_xml "/user/create", users(:admin_user).login, 'abracadabra', {}
authenticated_get_xml "/users", users(:admin_user).login, 'abracadabra', {}
end
private
def authenticated_post_xml_to_user_create(postdata = @@foobar_postdata, user = users(:admin_user).login, password = 'abracadabra', headers = {})
authenticated_post_xml "/user/create", user, password, postdata, headers
authenticated_post_xml "/users", user, password, postdata, headers
end
def assert_404_invalid_xml

View file

@ -86,5 +86,11 @@ class ActionController::IntegrationTest
def assert_401_unauthorized
assert_response_and_body 401, "401 Unauthorized: You are not authorized to interact with Tracks."
end
def assert_401_unauthorized_admin
assert_response_and_body 401, "401 Unauthorized: Only admin users are allowed access to this function."
end
end