Facebook Auth log out with Rails and Parse - ruby-on-rails

I am having trouble finding a way to log out from facebook. We are logging in using window.location = '/auth/facebook' which redirects the user to a facebook login page, and calls a callback route /auth/facebook/callback(declared in developers.facebook.com) to a method in my session_controller/create.
The session_controller/create method looks like this
def create
#get auth hash from omniauth
auth = auth_hash
#data = {}
#session_data = {}
#data['id'] = auth['uid']
#data['access_token'] = auth['credentials']['token']
#time must be in iso format, see parse rest api for details under linking
#expiry = Time.at(auth['credentials']['expires_at']).iso8601
#data['expiration_date'] = #expiry
#create new linking user object
user = Parse::User::Facebook.new(#data)
# add other user information to body of PARSE::USER::FACEBOOK instance
user.body['email'] = auth['info']['email']
user.body['auth'] = true
user.body['fullname'] = auth['info']['name']
user.body['ip'] = request.remote_ip
user.body['image'] = auth['info']['image'] if auth['info']['image']
user.body['admin'] = false
user.body['facebookId'] = auth['uid']
user.body['facebookToken'] = auth['credentials']['token']
user.body['has_seen_web_tutorial'] = false
#current_user = user.save
#save necessary session information
session['name'] = #current_user['fullname']
session['points'] = #current_user['points']
session['objectId'] = #current_user['objectId']
session['sessionToken'] = #current_user['sessionToken']
session['image'] = #current_user['image']
session['location'] = #current_user['location']
#session_data['name'] = session['name']
#session_data['fullname'] = #current_user['fullname']
#session_data['points'] = session['points']
#session_data['objectId'] = session['objectId']
#session_data['image'] = session['image']
if auth['info']['image']
File.open('temp_face.png', 'wb') do |file|
file << open(auth['info']['image'], :allow_redirections => :safe).read
end
photo = Parse::File.new({
:body => IO.read("temp_face.png"),
:local_filename => "temp_face.png",
:content_type => "image/png"
})
photo.save
#user.body['image'] = photo
end
image = Parse::Object.new("ImageUploads")
image['fileKey'] = photo
image['owner'] = Parse::Pointer.new({"className" => "_User", "objectId" => session['objectId']})
image['type'] = 'profile'
#image['location']
saved_image = image.save
redirect_to listing_index_path
end
I am having trouble trying to log out. Very new to rails. Any help please?
Thank you

Related

Get Input from form for API url Request in rails?

I'm new to Rails and I'm trying to make a simple weather API to get weather by zipcode
is there a way to get the zipcode from user input from a simple form, this will be just for learning so I'm not trying to make users devise, or users model
require 'net/http'
require 'json'
#url = 'http://api.openweathermap.org/data/2.5/weather?zip=#{zipcode}&appid=APIKEY'
#uri = URI(#url)
#response = Net::HTTP.get(#uri)
#output = JSON.parse(#response)
actually I figured it out, i needed to add
def zipcode
#zip_query = params[:zipcode]
if params[:zipcode] == ""
#zip_query = "Hey you forgot to enter a zipcode!"
elsif params[:zipcode]
# Do Api stuff
require 'net/http'
require 'json'
#url = 'http://api.openweathermap.org/data/2.5/weather?zip='+ #zip_query +'&appid=APIKEY'
#uri = URI(#url)
#response = Net::HTTP.get(#uri)
#output = JSON.parse(#response)
#name = #output['name']
# Check for empty return result
if #output.empty?
#final_output = "Error"
elsif !#output
#final_output = "Error"
else
#final_output = ((#output['main']['temp'] - 273.15) * 9/5 +32).round(2)
end
end
end
in the controller.rb file
and add
post "zipcode" => 'home#zipcode'
get "home/zipcode"
in the routes file
but I'm sure this is not the best practice

ruby/rails JSON to hash then changing array of the hashes then send back JSON

I have a rails app. I get JSON from 3rd party API. I would like to modify it to be able to send the proper JSON to another API. I was able to make a hash of it with JSON.parse, but I can't modify the hash properly and I don't know the preferred way to turn it back to JSON then.
In the get_own_events method I have the result array (code works properly till this). Now I'm trying to extract some attributes and returning the new formatted_result array which only contains the necessary, formatted attributes (I don't need the original result array.).
How can return/create the proper formatted_result array of hashes and then turn it back to JSON? In the code at the moment I get back the original hash not the new hash what I'm trying to create.
controller
#google = #user.socials.where(provider: "google_oauth2").first
#results_own = get_own_events(#google)
respond_to do |format|
format.html
format.json { render json: #results_own }
end
method
def get_own_events(social_object)
client = init_google_api_calendar_client(social_object)
old_token = client.authorization.access_token
service = client.discovered_api('calendar', 'v3')
result_raw = client.execute(
:api_method => service.events.list,
:parameters => { 'calendarId' => social_object.email,
'timeMin' => "2015-12-27T00:00:00+00:00",
'timeMax' => "2016-01-30T00:00:00+00:00" },
:headers => {'Content-Type' => 'application/json'})
result = JSON.parse(result_raw.body)['items']
formatted_result = result.each do |event|
title = event['summary']
if event['start']['dateTime']
start_time = event['start']['dateTime'].to_datetime.rfc822
end
if event['end']['dateTime']
end_time = event['end']['dateTime'].to_datetime.rfc822
end
if event['start']['date'] && event['end']['date'] && (event['start']['date'] != event['end']['date'])
all_day = true
start_allday_date = event['start']['date'].to_datetime.rfc822
end_allday_date = event['end']['date'].to_datetime.rfc822
end
formatted_event = {}
formatted_event['title'] = title
formatted_event['start'] = start_time || start_allday_date
formatted_event['end'] = end_time || end_allday_date
formatted_event['allDay'] = all_day || false
return formatted_event
end
return formatted_result
end
Changing .each to a .map may solve you're problem and go ahead and remove the return formatted_result at the end as you don't need it in Ruby because it's the last thing in your method and so
change this
formatted_result = result.each do |event|
...
return formatted_event
end
return formatted_result
to this
result.map do |event|
...
formatted_event
end
If you are trying to populate a new collection, use map instead of each. So,formatted_result = result.each do |event| should be formatted_result = result.map do |event|.
formatted_result = result.map do |event|
title = event['summary']
if event['start']['dateTime']
start_time = event['start']['dateTime'].to_datetime.rfc822
end
if event['end']['dateTime']
end_time = event['end']['dateTime'].to_datetime.rfc822
end
if event['start']['date'] && event['end']['date'] && (event['start']['date'] != event['end']['date'])
all_day = true
start_allday_date = event['start']['date'].to_datetime.rfc822
end_allday_date = event['end']['date'].to_datetime.rfc822
end
formatted_event = {}
formatted_event['title'] = title
formatted_event['start'] = start_time || start_allday_date
formatted_event['end'] = end_time || end_allday_date
formatted_event['allDay'] = all_day || false
formatted_event
end

Request Error Twitter-API Rails 4

I'm wondering how to limit the number of followers returned via the twitter api, or if there's a better way of returning the twitter followers of a user.
We've been challenged to create a twitter manager, and I've done most of the stuff, but I keep getting a request error when someone has a large amount of followers, as we're supposed to get the users from the twitter api and store them in a database, and the page usually times out or gives a twitter get error too many requests and locks me out for an hour. It's very hard to develop when this keeps happening, I was just wondering if there's a better way to do it?
Here is my code for the dashboard which is where the user details are returned and saved, and also where the followers are returned and save:
class DashboardController < ApplicationController
helper_method :logged_in?
def new
#just_updated = ""
Twitter.configure do |config|
# Test Account
config.consumer_key = "none-of-your-business"
config.consumer_secret = "none-of-your-business"
config.oauth_token = "none-of-your-business"
config.oauth_token_secret = "none-of-your-business"
end
#user = User.find(session[:user_id])
if #user.twitter_username.present? && #user.twitter_details_present == false
#twitter_user = Twitter.user(#user.twitter_username)
#user.no_of_followers = #twitter_user[:followers_count]
#user.profile_picture_url = #twitter_user[:profile_image_url]
#user.following = #twitter_user[:friends_count]
#user.twitter_nationality = #twitter_user[:location]
#user.no_of_tweets = #twitter_user[:statuses_count]
#user.twitter_details_present = true
#user.updated_at = Time.now
if #user.save
#just_updated = "We have just updated your follower details"
else
#just_updated = "There was a problem with your save1"
end
end
if (Time.now - #user.updated_at) < 10.minute && (#user.updated_at - #user.created_at) > 1.hour
Follower.where("owner = #{#user.id}").destroy_all
end
if #user.twitter_username.present?
if (#followers = Follower.where("owner = #{#user.id}")).count > 0
i = Follower.first.id
#followers.each do |follower|
if (Time.now - Follower.where("owner = #{#user.id}").first.updated_at) > 1.hour
if (follower_to_save = Follower.where(follower_id: follower[:id])).present?
follower_to_save[0].follower_username = follower[:screen_name].to_s
follower_to_save[0].owner = #user.id
follower_to_save[0].follower_nationality = follower[:location]
follower_to_save[0].no_of_followers = follower[:followers_count]
follower_to_save[0].following= follower[:friends_count]
follower_to_save[0].no_of_tweets = follower[:statuses_count]
follower_to_save[0].profile_picture_url = follower[:profile_image_url]
follower_to_save[0].updated_at = Time.now
if follower_to_save[0].save
#just_updated = "We have just updated your follower details"
else
#just_updated = "There was a problem with your save1"
break;
end
else
follower_to_save = Follower.new
follower_to_save.follower_id = follower[:id]
follower_to_save.owner = #user.id
follower_to_save.follower_username = follower[:screen_name]
follower_to_save.follower_nationality = follower[:location]
follower_to_save.no_of_followers = follower[:followers_count]
follower_to_save.following= follower[:friends_count]
follower_to_save.no_of_tweets = follower[:statuses_count]
follower_to_save.profile_picture_url = follower[:profile_image_url]
follower_to_save.updated_at = Time.now
if follower_to_save.save
#just_updated = "We have just updated your follower details"
else
#just_updated = "There was a problem with your save2"
break;
end
end
else
next
end
i=i+1
#sleep(1)
end
else
#followers = Twitter.followers(#user.twitter_username)
#followers.each do |follower|
follower_to_save = Follower.new
follower_to_save.follower_id = follower[:id]
follower_to_save.owner = #user.id
follower_to_save.follower_username = follower[:screen_name]
follower_to_save.follower_nationality = follower[:location]
follower_to_save.no_of_followers = follower[:followers_count]
follower_to_save.following= follower[:friends_count]
follower_to_save.no_of_tweets = follower[:statuses_count]
follower_to_save.profile_picture_url = follower[:profile_image_url]
follower_to_save.updated_at = Time.now
if follower_to_save.save
#just_updated = "We have just compiled your followers"
else
#just_updated = "There was a problem with your save3"
break;
end
#sleep(1)
end
end
else
#no_twitter_username = "Please go into settings and add your twitter username to start."
end
#followers = Follower.all.where("owner = #{#user.id}")
#follower_count = #followers.count
end
def logged_in?
if session[:user_id].present?
true
else
false
end
end
end
The code is pretty inefficient right now, but I'm just trying to get it working.

rails linkedin gem: how to scan all user fields for emptiness

quick question: i'm using the linkedin gem to pull user data, but my app breaks if a particular data field is blank on the user's linkedin profile. is there an optimal way to scan each profile for blankness in all data fields and pull only those that are present to prevent breaking?
here is my auth_controller...i know it is not DRY and in need of refactoring. Thanks!
require 'linkedin'
class AuthController < ApplicationController
def index
client = LinkedIn::Client.new(ENV['LINKEDIN_KEY'], ENV['LINKEDIN_SECRET'])
request_token = client.request_token(:oauth_callback =>
"http://#{request.host_with_port}/callback")
session[:rtoken] = request_token.token
session[:rsecret] = request_token.secret
redirect_to client.request_token.authorize_url
end
def callback
client = LinkedIn::Client.new(ENV['LINKEDIN_KEY'], ENV['LINKEDIN_SECRET'])
if session[:atoken].nil?
pin = params[:oauth_verifier]
atoken, asecret = client.authorize_from_request(session[:rtoken], session[:rsecret], pin)
session[:atoken] = atoken
session[:asecret] = asecret
else
client.authorize_from_access(session[:atoken], session[:asecret])
end
current_user = client.profile(:fields => %w(positions educations))
#user = current_user
educations = current_user.educations.all
positions = current_user.positions.all
companies = current_user.positions.all.map{ |t| t.company }
#current_company = companies[0]['name']
#past_company_one = companies[1]['name']
#past_company_two = companies[2]['name']
#past_company_three = companies[3]['name']
#current_industry = companies[0]['industry']
#past_industry_one = companies[1]['industry']
#past_industry_two = companies[2]['industry']
#past_industry_three = companies[3]['industry']
#first_name = client.profile(:fields => ["first_name"]).first_name
#last_name = client.profile(:fields => ["last_name"]).last_name
#headline = client.profile(:fields => ["headline"]).headline
#picture = client.profile(:fields => ["picture-url"]).picture_url
#school_one_name = educations[0]['school-name']
#school_one_degree = educations[0]['degree']
#school_one_field = educations[0]['field-of-study']
#school_one_start = educations[0]['start-date']['year'].to_s
#school_one_end = educations[0]['end-date']['year'].to_s
#school_two_name = educations[1]['school-name']
#school_two_degree = educations[1]['degree']
#school_two_field = educations[1]['field-of-study']
#school_two_start = educations[1]['start-date']['year'].to_s
#school_two_end = educations[1]['end-date']['year'].to_s
#current_title = positions[0]['title']
#past_title_one = positions[1]['title']
#past_title_two = positions[2]['title']
#past_title_three = positions[3]['title']
#current_start_date = Date::MONTHNAMES[positions[0]['start-date']['month']] + " " + positions[0]['start-date']['year'].to_s
#past_start_date_one = Date::MONTHNAMES[positions[1]['start-date']['month']] + " " + positions[1]['start-date']['year'].to_s
#past_end_date_one = Date::MONTHNAMES[positions[1]['end-date']['month']] + " " + positions[1]['end-date']['year'].to_s
#past_start_date_two = Date::MONTHNAMES[positions[2]['start-date']['month']] + " " + positions[2]['start-date']['year'].to_s
#past_end_date_two = Date::MONTHNAMES[positions[2]['end-date']['month']] + " " + positions[2]['end-date']['year'].to_s
#past_start_date_three = Date::MONTHNAMES[positions[3]['start-date']['month']] + " " + positions[3]['start-date']['year'].to_s
#past_end_date_three = Date::MONTHNAMES[positions[3]['end-date']['month']] + " " + positions[3]['end-date']['year'].to_s
end
end
considering your current code may break upon any unexpected values in the response and assuming it's happening in your above callback method, you may consider just applying quick'n'dirty exception handling to your code.
for example, by simply enclosing the potentially offending code in a begin / end block and using a rescueclause to handle any exceptions:
def callback
client = LinkedIn::Client.new(ENV['LINKEDIN_KEY'], ENV['LINKEDIN_SECRET'])
if session[:atoken].nil?
# ...code
else
#...code
end
# start handling exceptions here
begin
# ...potentially offending code here
current_user = client.profile(:fields => %w(positions educations))
# ...more code
#past_end_date_three = Date::MONTHNAMES[positions[3]['end-date']['month']] + " " + positions[3]['end-date']['year'].to_s
rescue
# oops, something happened:
# ...your code to handle the exception here
end
end

Omniauth for provider authentication in Rails API

I've got omniauth working flawlessly for my rails app on the web. I've also created an API for our iPhone app to interact and I'm trying to get omniauth to work.
Is there a way to pass an access token (received from the integrated iOS integration with the Facebook.app) to omniauth to create the provider entry in the database?
Right now in my web app I have an authentications controller with the following code
def create
omniauth = request.env["omniauth.auth"]
user = User.where("authentications.provider" => omniauth['provider'], "authentications.uid" => omniauth['uid']).first
if user
session[:user_id] = user.id
flash[:notice] = t(:signed_in)
redirect_to root_path
elsif current_user
user = User.find(current_user.id)
user.apply_omniauth(omniauth)
user.save
flash[:notice] = t(:success)
redirect_to root_path
else
session[:omniauth] = omniauth.except('extra')
flash[:notice] = "user not found, please signup, or login. Authorization will be applied to new account"
redirect_to register_path
end
end
In my user controller for the API I created the following:
def create
#user = User.new(params[:user])
#user.save
# Generate data for omni auth if they're a facebook user
if params[:fb_access_token]
graph = Koala::Facebook::API.new(params[:fb_access_token])
profile = graph.get_object('me')
#user['fb_id'] = profile['id']
#user['fb_token'] = params[:fb_access_token]
#user['gender'] = profile['gender']
# Generate omnihash
omnihash = Hash.new
omnihash['provider'] = 'facebook'
omnihash['uid'] = profile['id']
omnihash['info'] = Hash.new
omnihash['info']['nickname'] = profile['username']
omnihash['info']['name'] = profile['name']
omnihash['info']['email'] = profile['email']
omnihash['info']['first_name'] = profile['first_name']
omnihash['info']['last_name'] = profile['last_name']
omnihash['info']['verified'] = profile['verified']
omnihash['info']['urls'] = Hash.new
omnihash['info']['urls']['Facebook'] = profile['link']
omnihash['credentials'] = Hash.new
omnihash['credentials']['token'] = params[:fb_access_token]
omnihash['extra'] = Hash.new
omnihash['extra']['raw_info'] = Hash.new
puts omnihash
# Save the new data
#user.apply_omniauth(omnihash)
#user.save
end

Resources