I've set up some events where users can subscribe to calendar events via Outlook/Thunderbird/Iphone so on.
I use devise for authentication and in almost all controllers I have set up this devise method:
before_filter :authenticate_user!
The url for the Icalendar feed is:
/events/export_events.ics
When I remove the before_filter :authenticate_user! line basically you don't have to authenticate and then it's possible to subscribe to events.
I got it on the Phone/Thunderbird and Outlook.
When I uncomment this line I get errors on my Iphone which says:
Calendar Subscription
Unable to very account information.
When I enter my credentials I get rejected.
It seems like I have to add something to devise so users can authenticate via the Url.
The Rails log says:
Processing by EventsController#export_events as ICS
Completed 401 Unauthorized in 1ms
Any idea's how I could manage to authenticate this ?
Not important side notes but for the sake of completeness.
I use the Icalendar gem to create/transform my database events into valid Icalendar format.
in my events_controller.rb:
There is the export_events action which works like a charm:
It totally comes up to the authentication but someone might use this snippet for either understanding the problem or for own projects.
def export_events
#events = Event.first(10)
#calendar = Icalendar::Calendar.new
#events.each do |e|
event = Icalendar::Event.new
event.dtstart = e.start.strftime("%Y%m%dT%H%M%S")
event.dtend = e.end.strftime("%Y%m%dT%H%M%S")
event.summary = e.title
#calendar.add_event(event)
end
#calendar.publish
#headers['Content-Type'] = "text/calendar; charset=UTF-8"
#render :text => #calendar.to_ical
#stuff = #calendar.to_ical
respond_to do |w|
w.ics { render text: #stuff }
w.html{}
end
end
routes.rb:
resources :events do
collection do
get 'export_events'
end
end
I managed to authenticate.
I opened up the devise.rb file.
Where I had to uncomment this line:
config.http_authenticatable = true
Related
Currently I have an Ajax call via a button click that updates a shopping cart, but the controller that it posts to has the authenticate_user! before_filter applied, which is what I want, as a user must be logged in.
Because it's an ajax call I normally just get a 401 error and no redirect, so to solve this I have:
$(document).on "ajaxError", (event, request, settings) ->
if request.status == 401
window.location.href = '/users/login'
However this is causing me issues with getting the flash[:notice] to appear as it's lost by the time i get to the login page.
From doing some reading on various posts on here I understand that I can use flash.keep which would persist my message, but I think to do that I am going to have to change my approach on handling the redirect. If I can do this in the controller I could also use if request.xhr?, couldn't I?
My question is how would I add this functionality whilst keeping all existing functionality of the authenticated_user! helper method. From looking at the devise docs the helper is dynamically built, isn't it?
I know I could put a helper into my application controller:
def authenticate_user!
super
end
So expanding on that I have tried
def authenticate_user!
if request.xhr?
respond_to do |format|
format.html { redirect_to new_user_session_path }
end
else
super
end
But when clicking the update button, which is this
$(window).load ->
$('a[data-target]').click (e) ->
e.preventDefault()
$this = $(this)
if $this.data('target') == 'Add to'
url = $this.data('addurl')
new_target = "Remove from"
else
url = $this.data('removeurl')
new_target = "Add to"
$.ajax url: url, type: 'put', success: (data) ->
$('.badge-number').html(data)
$this.find('span').html(new_target)
$this.data('target', new_target)
I get this error in the console
Routing Error
No route matches [PUT] "/users/login"
Not sure where to go from here.
This sounds quite high-friction from the user point of view. If I click "add to cart", I expect the thing to be added to the cart. I certainly don't expect to be redirected to a login/signup page. At this point, I would just navigate away.
A better approach is, if user is not logged in, create a guest user and write its id to the cookies. Guest user has cart, can add stuff, etc.
Then, at checkout page, you offer the choice "login" / "sign up". In either case, you get a real user. At which point you migrate guest cart and delete the guest user.
Example:
def current_or_guest_user
return guest_user unless current_user
# current user exists. And we found a guest user
if session[:guest_user_id]
transfer_guest_user_stuff # cart, posts and what-have-you
guest_user.destroy
session[:guest_user_id] = nil
end
current_user
end
def guest_user
unless #cached_guest_user
#cached_guest_user = User.find_or_create_by(id: session[:guest_user_id], is_guest: true)
session[:guest_user_id] = #cached_guest_user.id
end
#cached_guest_user
end
As the first piece of advice, You could use Trubolinks gem which provide all AJAX functionality "in-box" and is default in Rails 4+.
As the second piece of advice, You could generate Users Controler ( rails generate devise:controllers Users) and\or Devise modules such as sessions. passwords and other controlers with Customize Devise Tools.
Additionally, You could customize before_filter in certain Controller's code, for example:
class TicketsController < ApplicationController
before_filter :store_location
before_filter :authenticate_user!, :only => [:new, :delete]
In this sample, :authenticate_user should be only for :new and :delete methods. Other methods not require users authentication ...
I hope it help You!
I will preface this saying that I know almost nothing about rails. But I am trying to fix this issue involving rails so any help would be greatly appreciated (and also, if you could dumb it down for me that would be great!)
We have a rails email notification set up for two of our sites. If a user fills out an application on our English site, then a notification email is sent to person A. If a user fills out an application on our French site, then a notification email is sent to person B.
However, at the moment it seems like all emails are going to person A regardless of whether an application is filled out on the English or French site. How can I fix this?
Here is the code from the admin_mailer.rb file:
class AdminMailer < ActionMailer::Base
default from: 'noreply#canwise.com'
def contact_email
#contact = Contact.last
mail to: 'email1#1test.com'
end
def application_email
#application = Application.last
mail to: 'email1#test.com'
end
def eps_contact_email
#contact = Contact.last
mail to: "email2#test.com"
end
def eps_application_email
#application = Application.last
mail to: 'email2#test.com'
end
def salesforce_application_failure(application)
subject = "Application #{application.id} submitted by #{application.firstName} #{application.lastName} failed to submit to salesforce."
mail(to: 'test#test.com', subject: subject) do |format|
format.text { render text: '' }
end
end
end
And here is the code from the application.rb file:
def email_notification
if provider == 'www.frenchsite.com'
AdminMailer.eps_application_email.deliver
else
AdminMailer.application_email.deliver
end
end
HELP PLEASE!
If the emails are all going to email1#test.com, then it only means that your provider for french is not matching 'www.frenchsite.com'. The 'if' statement is always resulting in false.
i'm having some issues trying to update an attribute outisde my web app (No route matches [GET] "/admin/justifications/19/approve").
The user should approve or reject a permission from their emails...
admin/justifications_controller.rb
class JustificationsController < BaseController
before_action :find_justification
# PATCH/PUT /admin/justifications/1/approve
def approve
#justification.approve
#justification.create_activity :approve, owner: current_user, recipient: #justification.user
redirect_to request.referer
end
# PATCH/PUT /admin/justifications/1/reject
def reject
#justification.reject
#justification.create_activity :reject, owner: current_user, recipient: #justification.user
redirect_to request.referer
end
routes
scope :admin, module: :admin do
resources :justifications, except: :all do
member do
patch :approve
patch :reject
end
end
...
end
Tho this works well in my web page, but it breaks when users try to open the generated links sent to their emails.
Is it something im missing here??
Any help would be great. Thnks!!
Your approve action is only available via PATCH or PUT and the link you press in your email sends the request via GET
There are lots of questions in SO asking how to send a different method than GET from the link you send in the email and the answer for that is: It is not possible. You have to open an GET action to be accessed from your email links.
There is no way to natively add links which send a PATCH request - Rails uses a data-method attribute together with some clever javascript to fake PATCH, PUT and DELETE requests.
However this only works if jquery-ujs is loaded in the client, which is problematic since many email clients and even webmail clients block emails from running javascript for security reasons.
What you need to do is add a GET route.
I'm currently working on a rails Spree application(v 1.3.x).
I have also another application that i have created couple of months ago just suppose myfirstapp.com that is live and so many users have created account on this application so they are registered users now.
So, now i want in my new application which is one i'm currently working on just suppose it is **mysecondapp.com to allow registered users (i.e users who created account on myfirstapp.com) to sign_in in my second app without using my secondapp signup proccess. They should authenticate from myfirstapp.com and get into my secondapp.**
Any way to achieve this?
I think you could use your first app authentication on the seconde one, you can create a link just like facebook or twitter with redirects to a controller and then this controller sends a request to your first app(you will need the security code to do that) and then get the response, save the data you want(user_id or account) and works great...
Api class using protect_from_forgery:
class ApiController < ApplicationController
protect_from_forgery :except => 'custom_login'
end
Doing this you will avoid the default rails protection, with verifies the
<%= hidden_field_tag :authenticity_token, form_authenticity_token -%>
commonly used on rails forms.
Then you can implement your secret hash code, and verifies it like:
class ApiController < ApplicationController
protect_from_forgery :except => :login_from_app2
def login_from_app2
if params[:authentication] == auth_hash
if login(params[:user_credentials])
render :text => "Success" #better you return a json
else
render :text => "Fail login" #better you return a json
end
else
render :text => 'Invalid security hash'
end
end
def auth_hash
"8f2e4b354f193744272fe246ca9e8bf5"
end
end
That way you have a code with only app2 will send on a "post" request to access app1
and you can control the login.
I dont know if this is 100% secure, i think it is, but i will be glad if anyone could explain why this is not a good approach in this case.
I am using Authlogic-connect to connect various service providers. There is a method in user.rb
def complete_oauth_transaction
token = token_class.new(oauth_token_and_secret)
old_token = token_class.find_by_key_or_token(token.key, token.token)
token = old_token if old_token
if has_token?(oauth_provider)
self.errors.add(:tokens, "you have already created an account using your #{token_class.service_name} account, so it")
else
self.access_tokens << token
end
end
When a service provider is already added it gives the error as stated in the has_token? method and the page breaks. I need to redirect the app to the same page and flash the error. How do i do this? I have overridden the method in my own user.rb so that I can change the code.
Hmm, well you could put a method that handles the error that has_token? throws, and tell your controller to redirect that exact error. something like this in your controller:
rescue_from OauthError::RecordNotFound, :with => :deny_access
then you can put
def deny_access
redirect_to your_view_path, :alert => "Too bad sucker" #some flash message
end
Or you could do something like this in the controller:
if complete_oauth_transaction.errors.present?
redirect_to your_view_path
else
# continue on with the normal code here
end
This is how you could generically handle errors. Your exact code will vary, as this is all we have to go off of.