vendredi 16 septembre 2016

Rails google analytics API crude implementation

Working on a simple Google Analytics API dashboard app where signed_up users can see their data and receive emails along with other stuff.

As of now only a crude setup is implemented where
1. Devise is implemented
2. current_user authorizes app with Google

Need to ensure if the code is setup properly, here it is
In /lib/google_api.rb

require 'google/apis/analytics_v3'

class GoogleAPI  

  GOOGLE_API_CLIENT_ID = 'xxx'
  GOOGLE_API_CLIENT_SECRET = 'xxx'
  GOOGLE_OAUTH2_URL = 'http://ift.tt/IlrJzQ'
  GOOGLE_ACCESS_TOKEN_URL = 'http://ift.tt/1yJFQ0y'
  GOOGLE_CALLBACK_URL = 'http://localhost:3000/google_callback' 

  attr_accessor :ga_id, :client, :user

  def initialize(user, ga_id=nil)
    @user = user
    @ga_id = ga_id if ga_id
    @client = Signet::OAuth2::Client.new(
        client_id: GOOGLE_API_CLIENT_ID,
        client_secret: GOOGLE_API_CLIENT_SECRET,
        authorization_uri: GOOGLE_OAUTH2_URL,
        scope: Google::Apis::AnalyticsV3::AUTH_ANALYTICS_READONLY,
        token_credential_uri: GOOGLE_ACCESS_TOKEN_URL,
        redirect_uri: GOOGLE_CALLBACK_URL,
        additional_parameters: { access_type: :offline, approval_prompt: :force }
    )
  end

  def authorization_uri
      @client.authorization_uri.to_s
  end

  def init_refresh_token(authorization_code)
    @client.update!(code: authorization_code)
    # @client.fetch_access_token!['access_token'] gives you the access token
    @client.fetch_access_token!['refresh_token']
  end

  def reauthorize!(refresh_token)
    @client.update!(refresh_token: refresh_token, grant_type: :refresh_token)
    access_token = @client.fetch_access_token!['access_token']
    @client.update!(access_token: access_token)
  end

  def init_service(refresh_token)
    self.reauthorize!(refresh_token)
    service = Google::Apis::AnalyticsV3::AnalyticsService.new
    service.authorization = @client
    service
  end


end  

In Views

<h1>Logged in as <%= current_user.email %></h1>
Click  <%= link_to 'here',  @google_oauth_service.authorization_uri %>  to authorize app.
<br>
Go to your - <%= link_to "Google Dashboard", analytics_path %>

In Application Controller

require "#{Rails.root}/lib/google_api"
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  def google_oauth_service
    if current_user.ggl_re_token
        render :notice => "Already Authorized"
    else
        @google_oauth_service = GoogleAPI.new(current_user, current_user.ga_id) 
    end

  end

end

The condition in application controller does not work, it still redirects to Google even if the User has already authorized.

In GoogleController.rb

require "#{Rails.root}/lib/google_api"
class GoogleController < ApplicationController
    before_action :authenticate_user!
    before_action :google_oauth_service

    def google_callback
        if params[:code]      

          google_oauth_service = GoogleAPI.new(current_user)
          refresh_token = google_oauth_service.init_refresh_token(params[:code])

          #store the refresh token in database for later access from server

          current_user.ggl_re_token = refresh_token
          current_user.save

          redirect_to url_for(:action => :analytics)
        end
    end

    def analytics
        google_oauth_service = GoogleAPI.new(current_user)
        # TODO next two commands in scheduled task
        @service = google_oauth_service.init_service(current_user.ggl_re_token) #refresh_token from your database  
        @account_summaries = @service.list_account_summaries  
    end

end

ISSUES FACING
1. Is the refresh_tokenreauthorize! method be perfect for production? See top google_api.rb
2. For current_user when the link is clicked, how to make sure if Analytics is already authorized for the current_user, it does not redirect to the Google page but to a simple notification?
I tried it by checking if a refresh_token is there in the User model but it still redirects.

Sorry if its too much too ask but this scenario is not uncommon.
If you were executing this with a user model, what are the steps/conditions you would ensure is setup for a foolproof implementation.

Aucun commentaire:

Enregistrer un commentaire