json and rails 3 http request - ruby-on-rails

Having a page which contains list of users of my site in json format .I am using jquery getJson to get the dat from that url but I need these page not to be accessible if the user tried to open it by http request.

You can filter a specific action using request.xhr? that checks the value of header[X-Requested-With] of the request.
def your_action
unless request.xhr?
render status: 404 # or what you want
return
end
# action code
end

Related

How to redirect user to sign in page if not logged in

I am trying to redirect the user to sign-in page if the user tries to access MyAccountController. Now the issue is that the sign-in route is defined in router.js and I am not able to figure-out a way to access vue routes in rails controller.
class MyAccountController < ApplicationController
before_action :authenticate_user!
before_action :require_user
private
def require_user
head(401) unless user_signed_in?
end
def authenticate_user
if user_signed_in?
super
else
redirect_to 'sign-in'
end
end
end
router.js
const SessionsVue = () => import('views/sessions/new.vue')
const routes = [
{ 'path': '/sign-in', component: SessionsVue, meta: { requiresAuth: true } }
]
You cannot access Vue routes in Rails controller. Vue code, which is just JavaScript code running in your browser, communicates to your Rails controller via HTTP requests and responses.
From here, it’s totally up to you how you choose to communicate somehow from a controller to the JS running in the browser.
You don’t have many options:
Response status
Response headers
Response body
Response statuses correspond to predefined messages. There’s a status that suits you perfectly: 401 Unauthorized. You could
head :unauthorized
from an action and check response status in Vue somehow.
Response headers and body don’t differ much: headers always transmit a table of keys/values, for the body you can pass any string, but most often for Vue you would choose a string with JSON, which is a table of keys/values as well.
You could pass a
{ errors: ["Unauthorized"], ok: false }
in the body and check those values in Vue somehow.

Any alternative to redirect_to in rails api only application?

I would like to redirect to another url in rails controller action. like
def action_name
redirect_to url
end
I know i can do it simply using the above method. But i want to redirect in only one action in all my application. because of this i don't want to include this in controller.
include ActionController::Redirecting
is there any other way to redirect to a uri in api only applications. Thanks.
You can use respond_with which will respond with a appropriate response depending on the request type and the status of the model you pass to respond_with.
def create
#thing = Thing.create(thing_params)
respond_with(#thing)
end
This will give 201 - Created status and a location header if the the request is successful and a 422 - Unprocessable Entity if the validations fail.
Alternativly you can use head to send a header only response with no body.
def action_name
head :not_found, location: url
end
Note that :not_found could be any appropriate HTTP status.
If your using Rails API:
Route your path, and take the params, and return:
redirect_to controller: "client", action: "get_name", params: request.query_parameters and return

Staging subdomains when application already has subdomains

My current Rails application has the following subdomains:
ui.myapp.com
api.myapp.com
I want to set up a staging environment, and I am wondering what is the best approach in order to set the domains.
Usually, I would do:
staging.myapp.com
But then, how do I access the UI/API sites?
Is it 'ok' to do:
ui.staging.myapp.com
api.staging.myapp.com
?
Assumption: The output from API call is expected in JSON format.
It will not be advisable to use separate subdomain for functionality like api.staging.myapp.com. You can always use the same url for web application and API
Better way would be to use same controller-action from Rails application but instead to return JSON output hash.
For example to get the users, you will have some code in users_controller.rb as
class UsersController < ApplicationController
def index
#users = User.all
respond_to do |format|
format.html do
render :index
end
format.json do
render :json => {:users => #users}
end
end
end
end
Now here if the request is html it will render the html page else it will return the json response.
staging.myapp.com/users will get you the html page of web application displaying users collection and that of staging.myapp.com/users.json will provide you the json response hash of users collection.
So, you will not need different subdomain to distinguish the api and normal site. But using format of request you can distinguish the functionality.
I hope this answers your question. If you still have any query feel free to ask.

Force Omniauth to use json for callback?

I'm attempting to integrate Omniauth into an API written in rails, to be used by an Android application. This means that I want to be able to handle the omniauth callback with JSON.
By default, Omniauth sends its callbacks to /auth/:provider/callback, is there a way that I can force Omniauth to instead send its callbacks to /auth/:provider/callback.json?
You can specify format in action where handling callback:
# in route.rb
match '/auth/:provider/callback' => 'authentications#create'
# in authentications_controller.rb
class AuthenticationsController < ApplicationController
def create
# your code here
respond_to do |format|
format.json { ... } # content to return
end
end
end
I managed to do that by inspecting the request object on my rails backend.
When I make the request on my app, I add data on the submition defining the format:
format: "json"
And the omniauth then makes the callback for
/auth/:provider/callback
Wich in my case matches
sessions#create
as an HTML request. But once there, if you look at your request object in rails, and search for the omniauth.params hash you'll see that one of the values there is the format passed on tha data of the initial request:
"omniauth.params"=>{"format"=>"json", "provider"=>"facebook", "code"=>"..."}
Its a mather of you searching for this "format"=>"json" and doing a render json as an answear.
I hope it solves your problem.
# app/controllers/users_controller.rb
def authenticate
#credentials = request.env['omniauth.auth']
render json: #credentials
end
# config/routes.rb
get '/auth/:provider/callback', to: 'users#authenticate', as: 'user_auth'
And then all requests made to /auth/:provider/callback will return a JSON response by default.

How do I redirect a page after successful validation with form_remote_for()?

I'm using form_remote_for() to do validation on a form's data so that my rails app can show the user errors without reloading the page. I'm having troubles redirecting the page if there are no errors. Here is my code:
def create
# Validate the data
if error_count > 0
render :update do |page|
page.replace_html(div_id, error_text)
end
else
# Save the data
redirect_to(page_to_go_to)
end
end
Everything in this method works fine except the redirect. The server claims it does a successful redirect and I believe it's the AJAX call that's being redirected. What I want to happen is have the page that contains the form to redirect. Is that possible?
I thought about this some more and realized that I needed the page to redirect instead of the request I was handling. So I tried the following and it works great.
def create
# Validate the data
if error_count > 0
render :update do |page|
page.replace_html(div_id, error_text)
end
else
# Save the data
render :update do |page|
page.redirect_to(page_to_go_to)
end
end
end

Resources