Created tests for backend_controller to cover security concerns, including #372 "user can add an action to another user's context via API". Modified backend_controller to close that hole and make the tests pass.

Added UserController#create to provide RESTful API for the admin user to create a new user in the system. This may be useful for the folks who have generously opened their Tracks installs to others. I have plans to document the RESTful API stuff at some point and write a Ruby wrapper.

Created a class method User.get_salt that wraps all calls to the SALT constant so that unit-tests can be always run with the default salt (I was previously needing to modify my environment.rb to run tests). 

Replaced usages of assert_success in tests with assert_response :success because assert_success is deprecated.



git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@313 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
lukemelia 2006-08-25 02:25:18 +00:00
parent 14c8516002
commit 3002fcf2f1
12 changed files with 264 additions and 44 deletions

View file

@ -4,9 +4,8 @@ class BackendController < ApplicationController
web_service_scaffold :invoke
def new_todo(username, token, context_id, description)
if !check_token_against_user_word(username, token)
raise "invalid token"
end
check_token_against_user_word(username, token)
check_context_belongs_to_user(context_id)
item = @user.todos.build
item.description = description
@ -17,31 +16,34 @@ class BackendController < ApplicationController
end
def list_contexts(username, token)
if !check_token_against_user_word(username, token)
raise "invalid token"
end
check_token_against_user_word(username, token)
@user.contexts
end
def list_projects(username, token)
if !check_token_against_user_word(username, token)
raise "invalid token"
end
check_token_against_user_word(username, token)
@user.projects
end
protected
private
# Check whether the token in the URL matches the word in the User's table
def check_token_against_user_word(username, token)
@user = User.find_by_login( username )
unless ( token == @user.word)
render :text => "Sorry, you don't have permission to perform this action."
return false
raise (InvalidToken, "Sorry, you don't have permission to perform this action.")
end
end
def check_context_belongs_to_user(context_id)
unless @user.contexts.exists? context_id
raise (CannotAccessContext, "Cannot access a context that does not belong to this user.")
end
true
end
end
class InvalidToken < RuntimeError; end
class CannotAccessContext < RuntimeError; end

View file

@ -1,6 +1,6 @@
class UserController < ApplicationController
layout 'standard'
before_filter :login_required
prepend_before_filter :login_required
def index
render_text "This will be our jumping-off point for managing user functions!"
@ -10,6 +10,44 @@ class UserController < ApplicationController
render_text "You'll only be allowed to go here if you're an administrator."
end
verify :method => :post,
:only => %w( create_user ),
: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/cpa/create_user
#
def create
admin = User.find_admin
#render_text "user is " + session["user_id"].to_s + " and admin is " + a.id.to_s
unless session["user_id"].to_i == admin.id.to_i
access_denied
return
end
unless request.content_type == "application/xml"
render_failure "Content Type must be application/xml."
return
end
unless check_create_user_params
render_failure "Expected post format is xml like so: <request><login>username</login><password>abc123</password></request>."
return
end
user = User.new(params[:request])
user.password_confirmation = params[:request][:password]
unless user.valid?
render_failure user.errors.full_messages.join(', ')
return
end
if user.save
render :text => "User created.", :status => 200
else
render_failure "Failed to create user."
end
end
def preferences
@page_title = "TRACKS::Preferences"
@prefs = @user.preferences
@ -68,5 +106,21 @@ class UserController < ApplicationController
return false
end
end
private
def render_failure message, status = 404
render :text => message, :status => status
end
def check_create_user_params
return false unless params.has_key?(:request)
return false unless params[:request].has_key?(:login)
return false if params[:request][:login].empty?
return false unless params[:request].has_key?(:password)
return false if params[:request][:password].empty?
return true
end
end