devise not set flash messages when dealing with ajax request - ruby-on-rails

When user wants to perform an action that need him to login in first, devise will redirect him to the signin page and set a flash message: 'Please signin or signup before continue'. This works well with no-ajax request. But with an ajax request that also need signin first, it will response with 401 error and we should handle it manually as follows:
$.ajax({
url: '/books/user_score',
type: 'POST',
data: { score: value, book_id: book_id },
dataType: 'json',
success: function(data) {
bookStarWidget.data('starInfo', data.book_star);
setVote(bookStarWidget);
$("[name='my_vote']").rating('disable');
},
error: function(jqXHR, textStatus, errorThrown) {
if (jqXHR.status == 401) {
window.location.assign('/users/sign_in');
}
}
});
In the above code, we manually open the signin page when received the 401 error devise sends out.
The problem is that there is NO flash message set in this way. So could someone knows how to set the flash message as usual to keep a consistent behavior?

It looks like you're using javascript to set the location in the error case. Devise has a configuration option that will redirect on failure instead of returning http headers. This setting defaults to true which forces you to handle failure on xhr manually. Here's the explanation from the source: https://github.com/plataformatec/devise/blob/master/lib/devise/failure_app.rb#L120
So, in your Devise config:
config.http_authenticatable_on_xhr = false
Try the unauthenticated ajax request again and Devise will do the redirect for you, which should set up the flash messages as you expect.

Related

What do I do with low Scores in reCAPTCHA v3?

I have set up reCAPTCHA v3 on my ASP.NET MVC project. Everything is working fine and is passing back data properly.
So the code below depends on another dll I have, but basically, the response is returned in the form of an object that shows everything that the JSON request passes back, as documented by https://developers.google.com/recaptcha/docs/v3
It all works.
But now that I know the response was successful, and I have a score, what do I do? What happens if the score is .3 or below? Some people recommend having v2 also set up for secondary validation (i.e. the 'choose all the stop signs in this picture' or 'type the word you see'). Is that really the only 'good' option?
Obviously the code isn't perfect yet. I'll probably handle the solution in the AJAX call rather than the controller, but still. What should I do if the score is low?
I read this article
reCaptcha v3 handle score callback
and it helped a little bit, but I'm still struggling to understand. I don't necessarily need code (although it would never hurt) but just suggestions on what to do.
VIEW:
<script src="https://www.google.com/recaptcha/api.js?render=#Session["reCAPTCHA"]"></script>
grecaptcha.ready(function () {
grecaptcha.execute('#Session["reCAPTCHA"]', { action: 'homepage' }).then(function (token) {
$.ajax({
type: "POST",
url: "Home/Method",
data: JSON.stringify({token: token }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
console.log('Passed the token successfully');
},
failure: function (response) {
alert(response.d);
}
});
});
});
CONTROLLER:
[HttpPost]
public void ReCaptchaValidator(string token)
{
ReCaptcha reCaptcha = new ReCaptcha();
Models.ReCaptcha response = new Models.ReCaptcha();
response = reCaptcha.ValidateCaptcha(token);
//response returns JSON object including sucess and score
if (response.Success)
{
//WHAT DO I DO HERE????
}
}
Ended up getting the answer from another forum. Basically, the answer is "anything you want". There is no right or wrong when handing a successful response.
So what could be done, is if the response is successful and CAPTCHA doesn't throw a flag, do nothing. But if CAPTCHA is unhappy, you could display an alert or a banner that says 'could not process', or you could even add in CAPTCA version 2, which would make them do the picture test or the 'I am not a robot' checkbox, etc.

Perform RedirectToAction in AJAX post call

I have passed the Model object from the View to controller action method through the AJAX post call. Inside the action method, we have a some business logic to be perform based on the received input fields. if business logic fails, then we will return the error message to user else, then we need to redirect the user to some other page. in this case, Redirection to other page is not working in the AJAX post call.
Could you please provide me the any alternative approach on this?
Note:- i need to perform this post operation in the AJAX call.
Thanks
You can simply check if the status is an error and if so redirect in your ajax call
$.ajax({
url: '/ThingToDo/',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: data,
success: function (status) {
if (!status.error) { alert(!status.error); }
else { window.location.href = "/Redirecthere/"; }
}

JQuery Mobile & URL Parameters white flash on reload

I am using query mobile for a phonegap application, I am passing through parameters through the url to the next page.
For example:
main.html?id=1, menu.html?id=2 etc
To allow this I have to turn ajaxEnabled to false to allow it to pass through the information I need. In doing so I am unable to use transitions from page to page which means I get a white flash as the page reloads.
I am generating these links dynamically.
$.ajax({
url: 'URLTO WEBSERVER',
dataType: 'jsonp',
jsonp: 'jsoncallback',
timeout: 5000,
success: function(data, status){
$.each(data, function(i,item){
var list = '<li><a href="menu.html?idcat='+item.id_cat+'">'+item.category_cat+'</li>'
output.append(list);
});
},
error: function(jqXHR, textStatus) {
alert( "Request failed: " + textStatus );
output.text('There was an error loading the data.')
}
});
Is there a solution?
you can use method jquery serialize data for your paramater.
via changePage method in jquery
I hope solved :D
I think he is concerned about the "white plash page" that happens after the request is completed from server and then he calls changePage.
He is not worried about how to send parameters to server etc. This is assuming all that is working fine.

Rails Devise 401 from Safari Extension

I'm trying to make a simple $.ajax request to a Rails app running locally.
The request works without any issues from the console but when I make the call from the safari extension the app returns a 401 Unauthorized. I'm not sure if I need to create an api token for each user and pass that in the url string to authenticate or if there's a simple reason why devise is not processing the request even though I'm logged in. My guess is that the culprit is the before filter I have on my controller which looks like this:
before_filter: authenticate_user!
But again, I get the 401 when I am signed in to the app. Just for reference, here's the call I'm making from the extension:
$.ajax({
type: 'GET',
url: 'http://localhost:3000/playlists.json?callback=?,
dataType: 'jsonp',
success: function(data) { console.log(data); },
error: function() { console.log('Uh Oh!'); },
jsonp: 'jsonp',
crossdomain: true
});
Any help would be much appreciated.
Ok figured it out. The cookie being set was set to expire after 'session' which basically means that as soon as you navigate away from the page the session is no longer there. Thus the extension did not have access to this extension cookie. The key was to set an expiration date by default on the session cookie which you can do like this in config/initializers/session_store.rb:
YourApp::Application.config.session_store :cookie_store, {
   :key => '_yourapp_session',
   :expire_after => 60*24*60*60
}
You can read more about cookie types here: http://en.wikipedia.org/wiki/HTTP_cookie#Session_cookie

How do you pass devise authentication details to a rails controller action?

I have a controller action that is expected to be called by jquery. Here's the call:
$.ajax({
url: "/comments.json",
type: "POST",
dataType: "json",
data: {
commentable_id: $("#addCommentForm").attr("data-site-update-id"),
commentable_type: 'SiteUpdate',
content: $("#addCommentForm textarea#content").val()
},
success: function(comment) {
}
});
It works just fine, but for some reason, "current_user" is nil inside of the controller. If I force authenticate_user! as a filter, rails returns an HTTP Unauthorized.
How can I pass the authentication details so that this controller action works with devise? Even better, is there a way I can make this transparent? I don't want to pass the authentication details over and over for each ajax request...
In Java, once a user is logged in... they are logged in. You don't have pass anything from url to url anymore - it's in a session somewhere and it's all occuring transparently. Is there a way I can do this with rails? I don't want to focus on these details.
Thanks
EDIT: The solution is to add the following to your javascript somewhere:
$(document).ajaxSend(function(e, xhr, options) {
var token = $("meta[name='csrf-token']").attr("content");
xhr.setRequestHeader("X-CSRF-Token", token);
});
Devise does maintain sessions.
This may be your problem.

Resources