Forum: Ruby on Rails RE: web services and dealing with before_filter

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Berger, Daniel (Guest)
on 2006-05-03 20:57
(Received via mailing list)
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

2) 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.

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

class WebserviceController < ApplicationController
   ...
   web_service :login, LoginService.new
end

4) 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
This topic is locked and can not be replied to.