codedecoder

breaking into the unknown…


Leave a comment

rails custom deliver method : sending email through API

I have explained sending email using ActionMailer class of Rails Framework in this post . Go through it first if you not clear on how rail deliver the email. Now our requirement here is that, we do not want the rail to deliver the email for us, But want to get it deliver through ThirdParty email service, which say provide designed templates for the email or advertisement on the email or some other benefits. Basically, we want the email to be delivered through some API rather then Rails. So we need custom email delivery method

Here, you need to understand below two things how action mailer work.

=> ActionMailer create a email object which contain evrything you see in any email : subject, to, from, body, header etc

=> deliver method send the email object to destination using setting specified in the configuration file.

So, our approach will be to keep the first part of action mailer as it is,  and override the deliver method used in the second step.

NOTE : For complete detail on sending email through rails is explained in this post.Here I will mention only the steps which is needed to deliver email through custom method. Step 1 and Step 2 are new addition to the last post and step 3 will override the configuration used earlier. Other things will remain same.

Step 1 : Write Your class which interact with the API

Let us call this file postman.rb and place it in the lib folder of our rails application.

NOTE : define your own code within the deliver! (will throw exception if some error) or deliver (will not throw any exception) method. I have simply shown a sample code from one of my application. It will not work for you as I have used dummy password

module MyFinanace
  class Postman

    def deliver!(message)
      deliver_type = message.header["deliver_type"]
      if deliver_type == "api"
        url = "http://mansel/esb-sunpower/outbound/emailService/"
        username = "mensalTemplate"
        password = "gateway13"
        rest_resource = RestClient::Resource.new(url, username, password)
        rest_resource.post prepare_payload(message), :content_type => "application/xml"
      else
        mail.perform_deliveries = false
      end
    end

     def prepare_payload message
      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
        <emailRequest>
          <payload>
            <from>#{message.from.first}</from>
            <to>#{message.to.join(';')}</to>
            <cc>#{message.cc.join(';') unless message.cc.nil?}</cc>
            <bcc>#{message.bcc.join(';') unless message.bcc.nil?}</bcc>
            <replyTo>#{message.reply_to.first.to_s unless message.reply_to.nil?}</replyTo>
            <subject>#{message.subject.to_s unless message.subject.nil?}</subject>
            <body>#{message.body.to_s}</body>
            <contentType>text/html</contentType>
          </payload>
          <messageType>default</messageType>
        </emailRequest>"
    end

  end
end

So you can see that, We have redefined the deliver! method and making API call within it to mansel service. We pass it all the required detail like subject, to, from, body etc in the payload and left up to mansel to deliver the message.

STEP 2: Add your class defined above to the delivery method of rails ActionMailer class

Rails by default support smtp delivery. Since we have added our own class to deliver the email we need to tell ActionMailer about it. We can achieve it with add_delivery_method of ActionMailer . We need to specify it the time our application boot up, so be will create a file say my_mailer.rb in initializer folder of our application and add below lines to it.

require 'postman'
ActionMailer::Base.add_delivery_method :my_finanace_smtp, MyFinanace::Postman

So we have named our custom delivery method as my_finanace_smtp and pointed it to Postman module of MyFinanace class . Now, whenever we start our application, we will have our custom delivery method available to ActionMailer.

STEP 3: configure your environment file to use your custom deliver method

Since now we are using custom deliver method , which will be handled by API outside our rails application, We will replace the configuration used in development.rb file in step 1 of this post with below two line.

  config.action_mailer.default_url_options = {:host => 'localhost:3000'}
  config.action_mailer.delivery_method = :my_finanace_smtp

That’s all, now everything will remain same as in the last post, but your email will be delivered through your custom email deliver method.

Reference:

http://guides.rubyonrails.org/action_mailer_basics.html


23 Comments

Sample API consumer or API client

The people who make API call are API consumer or API client. Those who build the API to expose there application, making it interact with other application are called API provider. I have created a sample API in this post . Any other application(the consumer) can make call to this API to register, update or delete the user on API provider database.

You can see that the API provider has documented the url, authentication, expected data type and data required to fulfil your request. Provided, you fulfil, those criteria  , you can write your API consumer code in any language. Here, we will stick to Ruby.

Ruby has inbuilt library, to manage , making API calls, retrieving the returned response and parsing it to  reuse it in your own application. Below are those library.

http://ruby-doc.org/stdlib-1.9.3/libdoc/net/http/rdoc/Net/HTTP.html

http://rubydoc.info/gems/rest-client/1.6.3/RestClient

You may directly, use the above two library, to write your API consumer class. But, being part of ruby community, you do not need to go in much depth 🙂 as a no of Gem are available, there : – rest-client , faraday , httparty . I am not in position, to make a comment on which one is best or advantage and disadvantage of them, as I have tried only rest-client.

Now Let us make a Application which will consume the API,  I have developed in this post. The API, provide functionality to manage user, so in our application we will not store user in our own database, but will register it , update and delete them with the API provider.

I am assuming that, you all have implemented users controller at some point of time, where you have implemented index , new, create, edit, update and destroy method. Here, the view, routes and everything remain same, only the Users controller code will change, as now, it will interact, not with your Databse, but with the API provider Database .

Let us create our Rails Apllication, which will consume the user management API

STEP 1: generate the rails app

we will call it api_consumer

$ rails new api_consumer

STEP 2: add rest-client gems to your Gemfile

gem ‘rest-client’

run bundle install on the terminal

$ bundle install

STEP 3: generate the user controller

$ rails g controller users

STEP 4: add the routes for users resource in your routes

ApiConsumer::Application.routes.draw do
resources :users
end

STEP 5: Write the users controller code.

Users controller will have, the same actions and flow as you have seen in your, users controller, except that, here you interact with API provider database, thorugh its API call. IF you see the API provider document, you can see that they have provided you the authentication, url and expected data format.

You just have to make a call to these URL and handle the returned data in your application. API now a days return, data in XML or json format in general, but in case they return data in some other format say SOAP, then you have to adjust your code accordingly. The API provider whose service we are going to use return XML data by default i,e if you do not provide format in URL, they will return XML data. But, I found it easy to handle json data, So while making the call, we will specifically ask for json data.

So below is our controller code :

NOTE : see the use of get post put and delete call of the REST client. It will decide which action of API provider will be called for certain URL

class UsersController < ApplicationController
  require 'rest_client'

  USERNAME = "myfinance" # needed to access the APi
  PASSWORD = "credit123" # needed to access the APi
  API_BASE_URL = "http://localhost:3000/api" # base url of the API

  def index
    uri = "#{API_BASE_URL}/users.json" # specifying json format in the URl
    rest_resource = RestClient::Resource.new(uri, USERNAME, PASSWORD) # It will create
    new rest-client resource so that we can call different methods of it
    users = rest_resource.get # will get back you all the detail in json format, but it
    will we wraped as string, so we will parse it in the next step.
    @users = JSON.parse(users, :symbolize_names => true) # we will convert the return 
    data into array of hash.see json data parsing here
  end

  def new

  end

  NOTE :  see below how we are passing the payload and content type while making the post call
  def create
    uri = "#{API_BASE_URL}/users"
    payload = params.to_json # converting the params to json
    rest_resource = RestClient::Resource.new(uri, USERNAME, PASSWORD)
    begin
      rest_resource.post payload , :content_type => "application/json"
      flash[:notice] = "User Saved successfully"
      redirect_to users_path # take back to index page, which now list the newly created user also
    rescue Exception => e
     flash[:error] = "User Failed to save"
     render :new
    end
  end

  def edit
    uri = "#{API_BASE_URL}/users/#{params[:id]}.json" # specifying format as json so that 
                                                      #json data is returned 
    rest_resource = RestClient::Resource.new(uri, USERNAME, PASSWORD)
    users = rest_resource.get
    @user = JSON.parse(users, :symbolize_names => true)
  end

  def update
    uri = "#{API_BASE_URL}/users/#{params[:id]}"
    payload = params.to_json
    rest_resource = RestClient::Resource.new(uri, USERNAME, PASSWORD)
    begin
      rest_resource.put payload , :content_type => "application/json"
      flash[:notice] = "User Updated successfully"
    rescue Exception => e
      flash[:error] = "User Failed to Update"
    end
    redirect_to users_path
  end

  def destroy
    uri = "#{API_BASE_URL}/users/#{params[:id]}"
    rest_resource = RestClient::Resource.new(uri, USERNAME, PASSWORD)
    begin
     rest_resource.delete
     flash[:notice] = "User Deleted successfully"
    rescue Exception => e
     flash[:error] = "User Failed to Delete"
    end
    redirect_to users_path
   end
 end

STEP 6 : Create the corresponding views to the controller action

index.html.erb

It will list all the user detail returned by the API, it will as usual, provide “create new user” link to create a new user, also each record will have a Edit | Delete link. clicking the edit link will take the user to edit page where they will modify there detail and the Delete action will delete the user.

<%= link_to "Create New User", new_user_path %>
<%if @users.present? %>
  <p>Below is the list of users</p>
  <table width="100%">
    <tr>
      <td>ID</td>
      <td>first_name</td>
      <td>last_name</td>
      <td>email</td>
      <td>Action</td>
    </tr>
    NOTE : the @users object in our index action is array of hash, which is generated 
    when be passed return data to JSON.parse method. If you handled data in some other
    way, modify the code below accordingly. say for xml data you have to use something like
    u.xpath("id").text instead of u[:id]
    <%@users.each do |u|%>
    <tr>
      <td><%=u[:id]%></td>
      <td><%=u[:first_name]%></td>
      <td><%=u[:last_name]%></td>
      <td><%=u[:email]%></td>
      <td>
        <%= link_to "Edit", edit_user_path(u[:id]) %> | 
        <%= link_to "Delete", user_path(u[:id]), :method => :delete %>
      </td>
    </tr>
   <%end%>
  </table>
<%else%>
  <p>No User is Found</p>
<%end%>

new.html.erb

Here, as usual, user will fill up his detail and on submit it will go to create action, which will call create action of API to create the new user.

<%= form_tag users_path, :method => :post do %>
   email : <%=text_field_tag :email%><br />
   first_name :<%=text_field_tag :first_name%><br />
   last_name :<%=text_field_tag :last_name%><br/><br/>
   <%=submit_tag "save"%>
<%end%>

edit.html.erb
User will modify, there detail and submit to update action, which in turn update the record on API provider data base.

<%= form_tag user_path, :method => :put do %>
   email : <%=text_field_tag :email, @user[:email]%><br />
   first_name :<%=text_field_tag :first_name, @user[:first_name]%><br />
   last_name :<%=text_field_tag :last_name, @user[:last_name]%><br/><br/>
   <%=submit_tag "update"%>
<%end%>

STEP 7 : see it working

both the API provider and API consumer are sample application running on my own local machine. I have fixed the port 3000 for the API provider application. so start the API provider application on 3000, which is by default

$ cd to_api_provider_folder

$ rails s # will start the API provider service ast 3000

NOTE : for API consumer code to work, The API provider application must be up and running

Start the API consumer application on some other port, say 3030

$ cd api_consumer

$ rails s -p 3030

Go to the index page of the application:

http://localhost:3030/users # it will show you all users with edit | delete link and also a create new user link. So remaining things are self explainatory, try it out  yourself


4 Comments

passing parameter with post method in REST

While making API call, you should avoid passing sensitive information like username, password, social security number etc in the url as anyone can easily read them. The safer way is to make call as post method and pass needed parameter in body. I find this security hole in one of my own code but rectified it before anyone can misuse it.

Below, is the code, which generate authentication token from Openam, which support SSO for my application. Authentication token is needed to perform all task like user creation, deletion etc on Openam. So any person who can get hold of my username and password can getback the authorization token also and hack in Openam

require 'rest_client'
 module Openam
 class Client

   attr_writer :base_url, :username, :password

   def initialize(base_url, username, password)
      @base_url = base_url
      @username = username
      @password = password
   end

   def generate_authorization_token
     uri = "#{@base_url}/authenticate?username=#{@username}&password=#{@password}"
     admin_authorization_token = RestClient.post(uri, 
                                          :content_type => "application/xml")
     admin_authorization_token.slice!(9..-1).strip
   end
  end
end

I have modified, the above generate_authorization_token method to use post method and pass parameter in body instead of url

def generate_authorization_token
   uri = "#{@base_url}/authenticate" # url to which request is made
   payload = {:username=>@username,:password=>@password} # hash containing 
                                                       username and password
   admin_authorization_token = RestClient.post(uri, payload, 
                            :content_type => "x-www-form-url-encoded")
   admin_authorization_token.slice!(9..-1).strip # this step will remove unwanted 
                                           charecter from the token
end

The main point here is the use of  “x-www-form-url-encoded” as content type which tell REST that url parameter is present in the Body and passing username and password parameter as hash in the payload


1 Comment

installing REST API tool in firefox

I have created a sample REST API in this post. To access any API service, You need to write REST client code in your application. But you can try out any API services in your browser itself, by installing one of the many available tools. Good REST client tools is available for both Firefox and Chrome. I will explain, installing one of the tool and how to use it in Firefox.

STEP 1 : Installing the REST client tool

=> open your Firefox browser

=>You can find the REST client tool, through below steps

click tool tab at top of browser  -> click web developer  from the list -> click get more tools ->click Extensions down the adds on tab -> search rest client -> install the one with the title : RESTClient, a debugger for RESTful web services by click the button add to Firefox

=> Once installed, you can see a brown square icon with a circle in it at top right hand side of the browser. click it to start the tool

STEP 2: Understanding the tool

The REST client UI in browser look like this

Firefox rest client

Firefox rest client

You can test any REST API with the above tool. To use any API, you need to have information about its various services, see the sample API created in this post and read its documentation. These are the things, you need to fill up in the above UI, before making a call.

Authorization :

It list various type of authorization you need to setup before accessing any API. In the sample API I have provided basic authorization with username and password. Thus, click on basic authorization, fill the username and password and click O.K. It is one time process and will set your authorization for the current session

Content Type :

You need to setup, the content type of your request body. In API documentation you can find various type of content type supported by it. You can set content type by : click on header -> click on custom header -> In the popup, fill up Content-Type in name field and application/xml or application/json or application/x-www-form-urlencoded or anyother as per your need  in the value field-> click O.K

This can be also a one time process and you do not need to change it untill, you want to try out with any other content type.

API Requests :

Set, proper method, url and body in the above Rest Client UI as specified by the API documentation and then click the send button

API Response :

Once, the request is completed, you can see Response tab appearing at the bottom with Header, Response Body(raw), Response Body(highlight),  Response Body(Preview). The Header will contain the status of the response i,e success or failed and the response body will contain the data returned by the API to you


23 Comments

Sample REST API in Rails

I have tried to define and explain API in this post.  I again, put it in simple words “API is program which let the user to use methods of your application from outside the application“. I will create a REST API here which will implement CRUD ( create, read, update, delete ) operation on users table from outside the application. I assume you all have implemented CRUD for user in your application. The API implementation will remain same, with below difference.

=> In normal case, you have form new.html.erb and edit.html.erb, which provide UI to user to register themselves and edit there profile respectively. But for API you do not need any view as a user do not interact with Your application directly, instead you specify that data, the third party should send to you.

=> There will be no new and edit action in controller, as we do not need any view here

=> In normal application we do user authentication with devise etc, We need to skip that and introduce http authentication

=> We do not do any redirect in our controller action, but just return some data with status code and success or failure message. We may return data in json or xml or any other formate say SOAP. As per convention, you should return data as requested by client calling your API services, so for json request return json data and for xml return xml data

=> API do not have any user interface like navigation link or form to fill up by user etc. So for API you need to document the things, so that third party can use it easily. I will write the documentation for the API we create here in STEP 4

STEP 1: writing the routes

namespace :api do
 resources :users, :defaults => { :format => 'xml' }
end

I have put the routes, within api namespace, in this way, it will not conflict with users controller of your actual application, if you have one. If you do not have any, you can simply use  resources :users, :defaults => { :format => ‘xml’ } , but I suggest to always use a namespace and group all the controller related to your API in api folder only. Also, I have set the default :formate here as xml . If you do not set it, rails will consider it as a html request if user forget to pass any formate

STEP 2: generating the model


class User < ActiveRecord::Base
  attr_accessible :first_name, :last_name, :email, :password, :password_confirmation, 
                  :temp_password

  validates :email, :first_name, :last_name, :presence =>true
  validates_uniqueness_of :email

end

Thus in model we have validated email and other things, the user calling our API must provide these things. Thus while creating a user the caller must pass email, :first_name and :last_name. we will  generate password  dynamically and let him change it later on

STEP 3 : generating the users controller

class Api::UsersController < ApplicationController
  http_basic_authenticate_with :name => "myfinance", :password => "credit123"

  skip_before_filter :authenticate_user! # we do not need devise authentication here
  before_filter :fetch_user, :except => [:index, :create]

 def fetch_user
    @user = User.find_by_id(params[:id])
  end

  def index
    @users = User.all
    respond_to do |format|
      format.json { render json: @users }
      format.xml { render xml: @users }
    end
  end

  def show
    respond_to do |format|
      format.json { render json: @user }
      format.xml { render xml: @user }
    end
  end

  def create
    @user = User.new(params[:user])
    @user.temp_password = Devise.friendly_token
    respond_to do |format|
      if @user.save
        format.json { render json: @user, status: :created }
        format.xml { render xml: @user, status: :created }
      else
        format.json { render json: @user.errors, status: :unprocessable_entity }
        format.xml { render xml: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @user.update_attributes(params[:user])
        format.json { head :no_content, status: :ok }
        format.xml { head :no_content, status: :ok }
      else
        format.json { render json: @user.errors, status: :unprocessable_entity }
        format.xml { render xml: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    respond_to do |format|
      if @user.destroy
        format.json { head :no_content, status: :ok }
        format.xml { head :no_content, status: :ok }
      else
        format.json { render json: @user.errors, status: :unprocessable_entity }
        format.xml { render xml: @user.errors, status: :unprocessable_entity }
      end
    end
  end
end

STEP 4 : creating API Documentation

Your API is ready with step 3, but how other people will use it. You need to tell them, how to use it. Let us Document the things

API USAGE DOCUMENT
___________________________________________________________________
Basic Authentication:
    username: myfinance
    password: credit123

Content Type :
   application/xml or application/json

Body:
   You can pass xml or json data in Body
   
   sample json body

    {
     "email" : "test@yopmail.com", 
     "first_name" : "arun", 
     "last_name" : "yadav"
    }

   Sample xml body

    <user>
      <email>"test@yopmail.com"</email>
      <first-name>arun</first-name>
      <last-name>yadav</last-name>
    </user>

NOTE : Content Type should be set to application/xml for xml data in body 
and to application/json for json data in body

API Requests:

=> listing users
   url: http://localhost:3000/api/users
   method: GET
   body : not needed

=> Retrieving User detail
  url: http://localhost:3000/api/users/:id 
  method: GET
  body : not needed

=> creating users
   url: http://localhost:3000/api/users
   method: Post
   Body : It can be xml or json

=> Updating User
  url: http://localhost:3000/api/users/:id 
  method: PUT
  Body : It can be xml or json
  
=> Deleting User 
  url: http://localhost:3000/api/users/:id 
  method: DELETE
  body : not needed

STEP 5: testing the API

You need to write a REST client to use any API. I have explained it in this post. You may also try it out by Installing any REST client in your browser. I have explained installing REST client for Firefox in this post.

You will find method, url, body. header, authentication etc field there, fill the detail from the documentation instep 4. On submitting the detail, you will get back response. Hope it works for you and you get the basic understanding of API creation 🙂


18 Comments

google drive download upload with oauth2 in rails

Now a days many people use to store their document online in their emails, google drive etc. There may be case, when user want to upload some document in proof of, say there loan application or other claims etc from cybercafe, where their local system is not available, so it is good idea to provide this feature in your application if it need user to upload some document. I will explain the implementation here.

STEP 1: Understanding the flow

-> google provide API to access its google drive.

To use google API you need to create a development account with it and get client_id and client_secret . These two will be needed to validate the application trying to connect with the google API. Infact, all API provider whether FB, twitter or any other needs client_id and client_secret  issued by them. More information of google drive API is availabe here .

-> User need to login to there google account to access their google drive

google provides single sign on (SSO) for its API. We will use oauth2 strategy for this. oauth2 gem is available to ease our task.

-> downloading the document of loged in user

We will use google-drive-ruby gem for it. it will manage all upload and download on behalf of the loged in user. The basic implementation is available here . In this post, I will download file from google drive to temp folder of the application. Once, you have the file you can write methods which let the user to download to his system or upload to some other place. But that part I will cover in some other post

STEP 2: Install the required gems

Add below to Gemfile

gem 'google_drive'
gem 'oauth2'

Run bundle install on project root

STEP 3: creating Google API credential

go to https://code.google.com/apis/console and login with your gmail credential. It will ask you to create a project. click the create project button and on the next page which list all the API services, click on drive api button, accept the term and conditions, now you will see that the API button become green and also API access link appear in the side bar. click it, you will see create oauth2 client button, on the next page enter the required detail. See here if you get in problem while creating the credential

I fill below details:

product name : myfinance

Product logo   : select any logo if you have

Home page Url: localhost:3000

Now, click the next button, select web application and click create client id , so Now you have the below detail .

Client ID : 565763748610-uo2pjbbpg544ujcnuu7j28b6bjsl5llf.apps.googleusercontent.com
Email address : 565763748610-uo2pjbbpg544ujcnuu7j28b6bjsl5llf@developer.gserviceaccount.com
Client secret :     UUpzejV2gtYlJe1sFVENYUGN
Redirect URIs :     http://localhost:3000/oauth2callback
JavaScript origins : http://localhost:3000

STEP 4 : creating user authentication with oauth2

oauth2 strategy works with below principal

-> You tell it the SSO url where a user will be authenticated. Here, we are authenticating with google so it will be https://accounts.google.com

-> You need to tell oauth where the authenticated user will be redirected back in your application with the response. In step 2, you have seen that the redirect URI is https://localhost:3000/oauth2callback i,e oauth2 will send back the user to this url, let us write a routes for this url. Add below line to config/routes.rb file

match ‘oauth2callback’ => ‘documents#set_google_drive_token’ # so now we will write our stuff in set_google_drive_token action of documents controller.

Let us first write a library  for user authentication with oauth. Create lib/google_drive folder and create google_docs.rb file in it. It will look like this

module GoogleDrive

  class GoogleDocs

    attr_writer :client_id, :client_secret, :redirect_uri

    def initialize(client_id, client_secret, redirect_uri)
      @client_id = client_id
      @client_secret = client_secret
      @redirect_uri = redirect_uri
    end

    def create_google_client
      OAuth2::Client.new(
        @client_id, @client_secret,
        :site => "https://accounts.google.com",
        :token_url => "/o/oauth2/token",
        :authorize_url => "/o/oauth2/auth")
    end

    def set_google_authorize_url
      client = create_google_client
      client.auth_code.authorize_url(
        :redirect_uri => @redirect_uri,
        :access_type => "offline",
        :scope =>
          "https://docs.google.com/feeds/ " +
          "https://docs.googleusercontent.com/ " +
          "https://spreadsheets.google.com/feeds/")
    end

  end
end

The create_google_client method instantiate oauth2 class and set_google_authorize_url send the user to gmail for login

STEP 5 : Writing the controller code

create documents_controller.rb file. It will look like this

  
require 'google_drive/google_docs'
class DocumentsController < ApplicationController
 before_filter :google_drive_login, :only => [:list_google_docs]

 GOOGLE_CLIENT_ID = "565763748610-uo2pjbbpg544ujcnuu7j28b6bjsl5llf.apps.googleusercontent.com"
 GOOGLE_CLIENT_SECRET = "UUpzejV2gtYlJe1sFVENYUGN"
 GOOGLE_CLIENT_REDIRECT_URI = "http://localhost:3000/oauth2callback"
  # you better put constant like above in environments file, I have put it just for simplicity
  def list_google_docs
    google_session = GoogleDrive.login_with_oauth(session[:google_token])
    @google_docs = []
    for file in google_session.files
      @google_docs  < < file.title     
    end   
   end

  def download_google_docs
    file_name = params[:doc_upload]
    file_path = Rails.root.join('tmp',"doc_#{file_name}")
    google_session = GoogleDrive.login_with_oauth(session[:google_token])
    file = google_session.file_by_title(file_name)
    file.download_to_file(file_path)
    redirect_to list_google_doc_path
  end

  def set_google_drive_token
    google_doc = GoogleDrive::GoogleDocs.new(GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,
                GOOGLE_CLIENT_REDIRECT_URI)
    oauth_client = google_doc.create_google_client
    auth_token = oauth_client.auth_code.get_token(params[:code], 
                 :redirect_uri => GOOGLE_CLIENT_REDIRECT_URI)
    session[:google_token] = auth_token.token if auth_token
    redirect_to list_google_doc_path
  end

  def google_drive_login
    unless session[:google_token].present?
      google_drive = GoogleDrive::GoogleDocs.new(GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,
                     GOOGLE_CLIENT_REDIRECT_URI)
      auth_url = google_drive.set_google_authorize_url
      redirect_to auth_url
    end
  end
end

We are authorizing the user in the before filter google_drive_login. after authentication it take user to the redirect action set_google_drive_token, here we can retrieve the authentication token from the params[:code] send back with oauth returned url. I have stored that token in session[:google_token], so that I do not need to authenticate the user again. In download_google_docs method we need the name of the file we want to download fron google drive and the path of file where we need to download it.

STEP 6: writing routes for the controller action

Add below routes to config/routes.rb

match 'oauth2callback' => 'documents#set_google_drive_token' # user return to this after login
match 'list_google_doc'  => 'documents#list_google_docs', :as => :list_google_doc #for listing the 
                                                                                  #google docs
match 'download_google_doc'  => 'documents#download_google_docs', :as => :download_google_doc #download

STEP 7: Generating the views

So ,in view list_google_docs.html.erb will list all the docs with a radio buttons(we are downloading one at a time for now) within a form,the form will submit to the download_google_docs action, which after downlaod will be redirected back to the listing page.

<div>Select The document You want to Download</div>
<%= form_tag download_google_doc_path do %>
<% @google_docs.each do |doc|%>
<div><%=radio_button_tag “doc_upload”, doc %> &nbsp;<%=doc%></div>
<%end%>
<%= submit_tag  “Download” %>
<%end%>

That’s all, You can see that, the selected file get downloaded to temp folder

 

Reference :

https://developers.google.com/drive/credentials


1 Comment

Installing openam on ubuntu

OpenAM provides open source Authentication, Authorization, Entitlement and Federation software. You can setup it to provide single sign on ( SSO ) for your different website. For example, say you are a banking organization having different sites for catering different vertical of your business (insurance, loans, deposits etc). Now, your user is same for all these sites, so no need to maintain separate user database for them. It can be manage by openam. You can create, update, delete and validate users of all your site with openam.

With, the short introduction of openam above, we will now proceed to install it on our ubuntu system. Detail installation instruction is available here.

STEP 1: Prerequisite

-> create fqdn for your system

fqdn is fully qualified domain name. You can read more on fqdn here on wiki. In simple word I can say that, You system should be accessible from browser. For your local system localhost(127.0.01) is fqdn. when you do localhost in browser it load a page with message “Its working”. Since, we are experimenting with openam in local, If localhost in your browser give “Its working” message, you are ready to proceed to next step

-> Install java # I will write a blog on this soon. For , now manage it yourself  🙂

-> Installing Application Server

A no of application server is available which work with openam. We will go with tomcat.  You can find detail instruction on tomcat installation in this post.

STEP 2: Downloading openam

You can download latest stable version from here.  extract the downloaded folder. The extracted folder have name like openam_10.1.3, where 10.1.3 is the version number. remove the version number i,e rename to just call it openam. If you do not, in url you have to type openam_10.1.3  instead of openam.

STEP  3: Put openam in tomcat container.

Copy the openam folder of step 2 into /var/lib/tomcat7/webapps/

STEP 4: configuration change

openam will try to use usr/share/tomcat folder, So we must grant all access to this folder. So, run below command on the terminal

$ chmod 777 -R /usr/share/tomcat7 # this will give all permission to this directory

STEP 5: Running openam in browser

Assuming, you have installed tomcat as described here, and is running at port 8080. go to the browser and type below url.

http://localhost:8080/openam . It will take you to the basic configuration page http://localhost:8080/openam/config/options.htm , as you have yet not set username and password. It will give you two options : basic configuration and custom configuration . We will go with basic configuration to create a password and will do advance custom configuration from openam UI itself later on when needed. So , click on Default Configuration. Fill in your password and submit on successful password creation, you will be taken to the login page. Note that, you have only set password no username. It’s O.K as for default configuration the username is always amadmin. You can Login with below credential

username : amadmin

password: your_password.

Great…..You are loged in to openam, up and running.  Make configuration and other settings as per your need.