Storing user_likes with the Omniauth-Facebook gem - ruby-on-rails

Does anyone know where in the Auth Hash the user_likes are stored?
I've tried different combos:
auth.extra.raw_info.user_likes
auth.extra.raw_info.likes
I've got the permission, I just don't know how to get to the user_likes array.
Omniauth-Facebook gem
After some time (edit)
Alternatively I could do something like this using the HTTParty gem:
url = "https://graph.facebook.com/#{auth.uid}/likes&access_token=#{auth.credentials.token}"
#likes = HTTParty.get(url)
But I really want to know if its possible through the omniauth authentication process...

The omniauth-facebook gem uses the /me call to fill the raw_info hash. Per the facebook docs http://developers.facebook.com/docs/reference/api/user/, likes are not included in the user object but are a connection that can be accessed by calling https://graph.facebook.com/me/likes.

Hope this response though late, helps someone who is trying to figure out what is inside the different hashes part of auth hash object (schema reference: https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema)
Instead of trying different combinations (as posted in the question), one could simply render the object as an yaml to browser. Now page source of the browser output would give a clear picture of what is returned part of the auth object. Other option is to put a debug break and inspect the auth object in the callback controller (an ide would be very helpful in this case).
routes.rb
...
match '/auth/facebook/callback' => 'authentications#create'
...
authentications_controller.rb (or your controller that receives the call back)
class AuthenticationsController < ApplicationController
...
def create
# a simple code to understand the content of the auth object
render :text => request.env["omniauth.auth"].to_yaml
end
end

Related

Using responders gem with Rails 5

I'm using responders gem to dry up my controllers. Here's my current code:
class OfficehoursController < ApplicationController
def new
#officehour = Officehour.new
end
def create
#officehour = Officehour.create(officehour_params)
respond_with(#officehour, location: officehours_path)
end
def officehour_params
params.require(:officehour).permit(:end, :start, :status)
end
end
The problem that I'm facing right now is:
When I send valid parameters to create, it redirects to officehours/ as expected, however when I get 422 (validation error), it changes the URL from officehours/new to officehours/ (however it stays at the form page... idk why). The same happens for edit/update actions.
So, I want to stay at the .../new or .../edit when I get 422 error, how can I do this?
I don't think the issue comes from the gem. It just follows RESTFUL API, so does Rails.
That means the path for creating office hours is /officehours. Let's talk about your case:
There is nothing to say when we creating successfully. In your case, you redirect users to officehours_path.
When we creating unsuccessfully, we need to re-render the error form to users. But we were rendering the form in create action. As I said above, the URL for creating is /officehours, so you will see the /officehours instead of officehours/new
In order to keep the url /officehours/new:
We can set /officehours/new instead of /officehours for :create action. But you should not do that, are we going to break RESTFUL API?
Creating via AJAX to keep the URL persisted and you have to handle everything, eg: set flash messages on client, using Javascript to redirect in case of success, render the form error in case failure, ... And I don't think the gem help you dry up your application anymore.
Hope it helps!
I don't think so that it's a problem in responders gem, as I've noticed the same in rails applications. It seems like the default behaviour of rails applications.
take a look at this link for the explanation.

Rails API and Strong PARAMS

I am trying to create an api to create record Foo using the rails-api gem.
I initially ran the generator command to tell rails to create a controller for me and it created this:
def create
#foo = Foo.new(foo_params)
#foo.save
respond_with(#foo)
end
And this (Strong params):
def foo_params
params.require(:foo).permit(:bar)
end
This is pretty standard stuff and will work when using form_for to submit data to the create method.
In my case, I'm creating a stand-alone API web service that will only interact via external API calls.
So the issue that I'm experiencing, is I don't know how to post the :bar param via API. I tried posting a :bar param, but this leads to a 'param is missing or the value is empty: foo' error. I understand why this is happening, but I have no idea how to get around this...
Is there a better way to do this or should I provide the api param in a different way?
PS. Currently my api POST call looks like this:
http://localhost:3000/api/v1/foo.json?bar=test#mail.com
you cannot use the ?+argument at the end of the url for a POST HTTP request, it's only for a GET request.
You must use the data component of the HTTP call, that is not embedded in the URL
therefore, you cannot just make this from your browser address bar and must use curl or a great tool as Postman (free on the chrome App Store)
and in this data field, you can include the object you want to post (postman gives you a neat key value interface to do so)
let me know if you need more details on the curl function for command line calls, but I recommend that you use a nice tool as Postman, so useful if you're not used to these calls
EDIT : this is the URL to get Postman : https://www.getpostman.com

Update Twitter image and name after every login - Rails

My users can login only by Twitter and I'm using the omniauth-twitter gem (https://github.com/arunagw/omniauth-twitter).
Rails 4.1.2 and Ruby 2.1.0
It works perfectly, the only problem is that whenever a user changes his profile photo or name, the database is not updated with the changes.
How can I make my app to see after every login if any of the attributes is changed and if so, to update the database with them?
Thank you very much.
You should be able to add some code to your twitter callback action -- the action that is called by the path /auth/twitter/callback -- to read from the OmniAuth::AuthHash that is returned to you via request.env['omniauth.auth']. Basically, omniauth-twitter packages up the OAuth Provider's response into a convenient objet and places it in the request hash. So... something like this:
def twitter
# ...
update_picture
end
def update_picture
auth = request.env['omniauth.auth']
current_user.picture = auth.info.image
# or whatever
end
FYI: The OmniAuth::AuthHash object is basically a hash with benefits. It is an instance of a Hashie object, in case you're interested in learning more. (Off the top of my head, I think it's a Mash hash.)
Also, you can find and example return response here, in the omniauth-twitter readme.

Subclassing Ruby Gem?

As a RoR newbie, I'm trying to understand how/where to correctly subclass a gem.
I'm using the ruby-box gem (https://github.com/KonaTeam/ruby-box) in my application, and attempting to follow the example on their github page where they subclass session.rb in order to obtain a refreshed token as follows:
class MyBoxSession < RubyBox::Session
# override call to refresh token so we can update the tokens store
def refresh_token(refresh_token)
ut = MyTokens.where(refresh_token: refresh_token, provider: 'box').first
begin
super
ut.access_token = #access_token.token
ut.refresh_token = #access_token.refresh_token
ut.save!
rescue OAuth2::Error => e
# token pair must just be bad
ut.destroy
end
end
end
I'm my box controller I use ruby-box to create the initial session, but I'm unclear on where I would add in the code above? In the box controller, or do I need to pull in session.rb?
Any and all assistance is greatly appreciated. Thanks.
If you write just a ruby script, put the code inline. If you are using rails I believe in library lib/, and when you have need just call a library methods from a controller/helper. If the connection is persisted, initialize it once on startup.

Passing parameters through OmniAuth

I need to pass some parameters to callback action. Judging from the source code, OmniAuth should add query string to callback URL but strangely it does not. When I open
/auth/facebook?from=partner
...and get redirected to Facebook, return_url is just
/auth/facebook/callback
...without any parameters.
After struggling with all the above answers, I figured out what to do regarding Facebook, which by default does not display the params in request.env["omniauth.auth"].
So -- If you are using a query string for the callback, similar to something like this:
"/auth/facebook?website_id=#{#website.id}"
The only way to get that website_id param is by using request.env["omniauth.params"]. NOTE: MAKE SURE YOU USE omniauth.params and not omniauth.auth -- this one tripped me up for a while.
Then, to test this out, you can inspect it within your controller action (notice the RAISE line...):
def create
raise request.env["omniauth.params"].to_yaml
# the rest of your create action code...
end
You should see your parameter there. Great. Now, go back to your controller and remove that RAISE line. Then, you can access the param as follows in your controller action:
params = request.env["omniauth.params"]
website_id = params["website_id"]
NOTE: in params["website_id"] you need to use quotes and NOT a symbol.
I guess the cookie thing works but why do all that when you can use the state variable as documented here: https://github.com/mkdynamic/omniauth-facebook
This is how I used it:
when creating the url you can just add state in the Query String and it will be available in the callback url as well.
user_omniauth_authorize_path(:facebook, :display => 'page', :state=>'123') %>
now the callback url will be
http://localhost:3000/users/auth/facebook/callback?state=123&code=ReallyLongCode#_=_
Now in the callback handler you can process the state
You can use the :params options, as in
omniauth_authorize_path(:user, :facebook, var: 'value', var2: 'value2' )
and later in the callback you can access request.env['omniauth.params'] to get the hash! :)
(copied from this answer)
What you want to do is dynamically set your callback to include the partner name in the url (not the url parameters), on a per authentication transaction basis, depending on which partner was involved. This means setting the callback url dynamically, for each authentication request. See this blog post to get started. The callback url automatically drops the url parameters, as you've noticed, so doing this with parameters won't work.
So, if instead of trying to pass the partner name/id in as a parameter (which is dropped), you structured your routes so that the partner_id and OmniAuth provider were part of the callback url, then you'd have something like:
/auth/:omniauth_provider/callback/:partner_id
...where a valid callback would be something like
/auth/facebook/callback/123456
...then you would know that a given callback came in from facebook, with partner id 123456
OmniAuth already has a built-in way to know where the user was, it's called "origin" as documented here:
https://github.com/intridea/omniauth/wiki/Saving-User-Location
You know, I think I might be trying to solve this the hard way.
Cookies might be the answer. I think you can solve this by having your login action store a cookie, and then redirecting to the proper /auth/:provider path for authentication, and when the callback is triggered (in SessionsController#create), you just read the cookie back to know where to redirect them to.
So, right now, your "login with facebook" link (or whatever you have you in your app) probably goes to /auth/facebook. Instead if you created a custom action like
POST /partner_auth
...and called it with the url...
POST example.com/partner_auth?from=partner&provider=facebook
Then you might have a controller like:
class PartnerAuth < ApplicationController
def create
cookies[:from] = params[:from] # creates a cookie storing the "from" value
redirect_to "auth/#{params[:provider]"
end
end
Then in the SessionsController#create action, you would have...
def create
...
destination = cookies[:from]
cookies[:from].delete
redirect_to destination # or whatever the appropriate thing is for your
# app to do with the "from" information
end
I tried to build a demo app to accomplish what I'd outlined in the other answer, but you're right - it was too complicated to try to dynamically inject a custom callback into the OmniAuth code. There is a configuration option to override the default callback, but it doesn't appear to be easy to set it dynamically.
So, it dawned on me that cookies would be way simpler, user-specific, and since you theoretically only need to store this from information for a very short time (between when the user tries to authenticate, and when the callback is triggered), it's no big deal to create a cookie, and then delete it when the callback gets hit.
Use the 'state' Variable. Facebook allows the user to set a STATE variable.
Here is how I did it, I appended the AUTH URL with ?state=providername
http://localhost/users/auth/facebook?state=providername
This param is returned to me at Callback as params['providername']
I devised the solution from the original Omniauth Path Method
user_omniauth_authorize_path(:facebook, :display => 'page', :state=>'123') %>

Resources