RE: web services and dealing with before_filter


#1

Here’s how I ultimately decided to deal with this issue in case
anyone is interested:

  1. Created a LoginApi web service. In login_api.rb:

class LoginApi < ActionWebService::API::Base
api_method :login,
:expects => [:string, :string]
end

  1. Created a LoginService class. In login_service.rb:

class LoginService < ActionWebService::Base
web_service_api LoginApi
def login(cuid, password)
if User.login(cuid, password)
User.find_by_cuid(cuid)
end
end
end

This assumes a User.login and User.find_by_cuid
method in the User model somewhere. Adjust as needed.

  1. Added the appropriate line to the web service controller.
    In webservice_controller.rb:

class WebserviceController < ApplicationController

web_service :login, LoginService.new
end

  1. Within my ApplicationController (application.rb) I
    modified my authorize filter like so:

require ‘rexml/document’
include REXML

class ApplicationController < ActionController::Base

User must authorize to get to any screen

before_filter :authorize, :except => :login
model :user

private

def authorize
# If the http path requested is ‘/webservice/api’ assume it’s
# a remote call and give them a chance to login.
if session[:user].nil? && request.env[‘PATH_INFO’] ==
‘/webservice/api’
doc = Document.new(request.env[‘RAW_POST_DATA’])
elements = XPath.match(doc,
“/methodCall/params/param/value/string”)
cuid, password = elements.map{ |x| x.text }
session[:user] = LoginService.new.login(cuid, password)
end

  unless session[:user]
     flash[:notice] = "Please log in"
     session[:jumpto] = request.parameters
     redirect_to :controller => "login", :action => "login"
  end

end
end

Adjust the ‘/webservice/api’ path as needed.

Sample xmlrpc client:

require ‘xmlrpc/client’

rpc = XMLRPC::Client.new(‘localhost’, ‘http://localhost/webservice/api’,
3000)

rpc.call(‘login.Login’, ‘user’, ‘XXX’) # Only login once
p rpc.call(‘hardware.FindHardwareById’, 2)
p rpc.call(‘hardware.GetAllHardware’)

This allows the end programmer to login just once within their code,
instead
of having to login on a per-request basis.

I’m not sure how robust or secure this is, so I’m open to comments and
suggestions.

Regards,

Dan