Rails webcal subcription url with user authentication token; - ruby-on-rails

I am trying to create a link for user of my app to use to subscribe to their account calendars. I have a link that works that I generate in rails calendar_publisher_lists_url(:format => :ics, :only_path => false,:protocol => "web cal")
which generates a link like webcal://mywebsite.com/calendar.ics
However this only works if the user is logged in. I need for the link to work when the calendar is automatically updated, even if the user is not logged in. Thus I need to generate a link that would look like:
webcal://123#mywebsite.com/calendar.ics where '123' is the authentication token for the user.
How do I generate this url?

What's wrong with putting it onto the URL as attribute?
calendar_publisher_lists_url(:format => :ics, :only_path => false,:protocol => "webcal", :authentication_token => current_user.authentication_token)
webcal://mywebsite.com/calendar.ics?authentication_token=123
I mean apart from the security issue...

If security is not an issue you could change the route to add an id.
match '/calendar/:id/calendar_feed', to: 'calendar#calendar_feed', :as => 'calendar_feed_path'
Then in your controller put
def calendar_feed
#user=User.find(params[:id])
respond_to do |format|
format.ics
end
end
And then add a view template, adjust to fit your needs with your logic (this code is from one of my projects):
BEGIN:VCALENDAR
METHOD:PUBLISH
VERSION:2.0
PRODID:-//UserCalendar//EN
X-WR-CALNAME:Name Of Website
CALSCALE:GERGORIAN
<% #users.each do |user| %> #change logic to fit your needs
<% user.day_offs.each do |day_off| %>
BEGIN:VEVENT
DTSTAMP:<%=Time.now.strftime("%Y%m%dT%H%M%SZ")%>
UID:<%=day_off.id%>
SUMMARY:<%= day_off.user.name.titleize %> | <%= day_off.do_type %>
DTSTART:<%= day_off.start_date.strftime("%Y%m%d") %>
<% end_day=day_off.end_date + 1.day %>
DTEND:<%= end_day.strftime("%Y%m%d") %>
END:VEVENT
<% end %>
<% end %>
END:VCALENDAR
Then the feed link would be
<%= link_to("Subscribe to Calendar", "webcal://www.nameofwebsite.com/calendar_feed/#{current_user.user_id}/calendar_feed.ics" ) %>

Related

New to Rails trying to pass month and year from a form to a url

I've completed Hartl's Rails Tutorial and am now working on a project that uses the simple_calendar gem.
I want to add a dropdown to allow users to quickly navigate to a specific month and year without having to click the "next" link multiple times.
So far I have managed to create the dropdown form but I can't figure out how to set up the controller to get the url with the form parameters on submit.
This is in the partial I created that renders at the top of the monthview calendar:
<%= form_with do |form| %>
<%= select_month( Time.now, {:field_name => 'month', :id => 'month'} ) %>
<%= select_year( Date.today, {:start_year => Time.now.year,:end_year => Time.now.year+3} ,{:field_name => 'year', :id => 'year'} ) %>
<%= submit_tag("Go", :id=>"button", :class=>"date-button", :name=>"submit") %>
<% end %>
Can anyone explain how I can write the controller code to pass those parameters so that the user goes to a link like https://mycalendar.com/calendar?year=2021&month=june
Thank you for your help.
You can read the parameters directly
<%= form_with do |form| %>
<%= select_month( params[:month].present? ? Date.strptime(params[:month], '%B') : Time.now, {:field_name => 'month', :id => 'month'} ) %>
<%= select_year( params[:year].present? ? Date.strptime(params[:year], '%y') : Date.today, {:start_year => Time.now.year,:end_year => Time.now.year+3} ,{:field_name => 'year', :id => 'year'} ) %>
<%= submit_tag("Go", :id=>"button", :class=>"date-button", :name=>"submit") %>
<% end %>
But you have to add a checking for invalid date/parameters, so better do the parsing in the controller side
You can grab parameters sent to a controller via params[:parameter]. This works for both GET and POST requests. In a GET request these parameters are passed through the url, ie. /calendar?year=2021&month=june, whereas in a POST request they are passed in a formBody object.
One of the best things to do in Rails is to look at your console when a request is made. It will tell you the route, controller, action, and parameters in the log.
For a GET request you might use the method below to get the parameters.
# controller
def calendar
year = params[:year]
month = params[:month]
end
Generally a form would be sent via a PUT (create) or PATCH (update) request (known together as POST). In that case you might have a model object that the form fields would be stored in, and you would grab the parameters through a sanitization procedure. This sanitization is very important to ensure malicious code isn't passed through to your database.
def create
#event = Event.new(event_params)
...
end
private
def event_params
params.require(:event).permit(:month, :year, :title)
end
Your form_with might need a url: '/calendar' and even a method: :get to turn it into a GET request and send it to the correct route.

Customizing the views in authy-devise

I am trying to implement two factor authentication via authy 2FA of twilio using devise-authy gem.
I want to customize the views with three pages for 2FA.
first page - My login page where user enters username and password, on submit it will be redirected to a page
Second page - In this page he can select the 2FA method to receive the code via phone or sms after which he is redirected
Third page - Here he finally enters the code.
I am able to configure the first two pages.
My PROBLEM is that in the third page, where i am setting up the authy form for code verification, I am getting error undefined method id for nil class
<%= verify_authy_form do %>
<legend><%= I18n.t('submit_token_title', {:scope => 'devise'}) %></legend>
<%= label_tag :token %>
<%= text_field_tag :token, "", :autocomplete => :off, :id => 'authy-token' %>
<label>
<%= check_box_tag :remember_device %>
<span><%= I18n.t('remember_device', {:scope => 'devise'}) %></span>
</label>
<!-- Help tooltip -->
<!-- You need to configure a help message. -->
<!-- See documentation: https://github.com/authy/authy-form-helpers#help-tooltip -->
<!-- <%= link_to '?', '#', :id => 'authy-help' %> -->
<%= authy_request_sms_link %>
<%= authy_request_phone_call_link %>
<%= submit_tag I18n.t('submit_token', {:scope => 'devise'}), :class => 'btn' %>
<% end %>
I am getting error in this line verify_authy_form
On inspecting the code of gem i found that i need #authy_id so i tried
<%#authy_id=User.find(session[:user_id]).authy_id%>
in view no still no success.
This is my Users::AuthyCustomController, where i have overridden some of the methods as stated in gem
class Users::AuthyCustomController < Devise::DeviseAuthyController
protected
def after_authy_enabled_path_for(resource)
my_own_path
end
def after_authy_verified_path_for(resource)
my_own_path
end
def after_authy_disabled_path_for(resource)
my_own_path
end
def invalid_resource_path
my_own_path
end
def authentication_sms
end
def authentication_phone
#authy_id=User.find(session[:user_id]).authy_id
# redirect_to user_verify_authy_path
# redirect_to user_verify_authy_path and return
end
end
I have googled, but I was not able to find a solution
I am getting error undefined method id for nil class
This is the form helper
def verify_authy_form(opts = {}, &block)
opts = default_opts.merge(:id => 'devise_authy').merge(opts)
form_tag([resource_name, :verify_authy], opts) do
buffer = hidden_field_tag(:"#{resource_name}_id", #resource.id)
buffer << capture(&block)
end
end
I belive that #resource is nil so when it does #resource.id triggers the error
I believe this form is managed from this controller action
# verify 2fa
def POST_verify_authy
token = Authy::API.verify({
:id => #resource.authy_id,
:token => params[:token],
:force => true
})
if token.ok?
#resource.update_attribute(:last_sign_in_with_authy, DateTime.now)
session["#{resource_name}_authy_token_checked"] = true
remember_device if params[:remember_device].to_i == 1
if session.delete("#{resource_name}_remember_me") == true && #resource.respond_to?(:remember_me=)
#resource.remember_me = true
end
sign_in(resource_name, #resource)
set_flash_message(:notice, :signed_in) if is_navigational_format?
respond_with resource, :location => after_sign_in_path_for(#resource)
else
handle_invalid_token :verify_authy, :invalid_token
end
end
and you can prove that by checking and including the relevant output from rake routes. So maybe you should debug that two pieces of code, the controller action is responsible to feeding #resource to the form

Select_tag login

I would like to have a drop down menu with a list of all the user names in the db. From there, I would like the user to choose his/her name and be able to click login and be taken to their respective page. At this point, a password is not needed. Currently, I have the following:
controller:
def login
#user = User.new
#users = User.all
# #user = User.find_by_id(:id)
# redirect_to user_path(#user)
end
view:
<%= form_for #user, url: '/login', html: {method: 'get'} do |f| %>
<%= f.label "Name" %>
<br/>
<%= select_tag :user, options_for_select(#users) do |users| %>
<%= link_to users.name, users %>
<% end %>
<br/>
<br/>
<%= f.submit 'Login' %>
<% end %>
I cannot seem to link the user to their path and also, i want to show the users name in the drop down menu. Currently, it shows a hexidecimal pointer.
Thank you in advance.
You shouldn't be making a new User object here: you just want to load one out of the database. What you want to do in the controller is just to set current_user to be one of the existing users, right?
Also you've got the form submitting back to the action which loads the form in, which seems weird. I would make it submit to a new action, like "set_current_user" which is a POST action.
in your login template:
<%= form_tag '/set_current_user' do %>
<%= f.label "Name" %>
<br/>
<%= select_tag "user_id", options_for_select(#users.collect{|user| [user.name, user.id] } %>
<br/>
<br/>
<%= submit_tag 'Login' %>
<% end %>
in the controller (you'll need to amend routes.rb to make the '/set_current_user' go to this action) you then need to set something which will keep the user logged in. The traditional way to do this is via session[:user_id], and to have a method current_user which uses this.
def set_current_user
session[:user_id] = params[:user_id]
redirect_to "/" and return
end
Your initial approach is reminiscent of how this sort of thing is normally handled, wherein you do have a form_for, but it's for a UserSession object rather than a User object.

passing options when using methods in a rails gem

I'm using this gem for Facebook authentication in my Rails app.
I'm having some issues in IE and I think it's because of an issue in the Javascript in this file -
If you look at line 52, it seems I can pass options into channelUrl.
I'm implementing a login button like this -
<%= fb_login(:text=>"Log in") %>
Can I do this from my app, or do I need to edit the gem?
If I look at the README, you should have a partial like this one:
<%= fb_connect_async_js %>
<% if current_facebook_user %>
<%= "Welcome #{current_facebook_user.first_name} #{current_facebook_user.last_name}!" %>
or
<%= "Hello #{fb_name(current_facebook_user, :useyou => false)}!" # link to facebook profile %>
<%= fb_logout_link("Logout of fb", request.url) %><br />
<% else
# you must explicitly request permissions for facebook user fields.
# here we instruct facebook to ask the user for permission for our website
# to access the user's facebook email and birthday
%>
<%= fb_login(:text => 'Log in', :perms => 'email,user_birthday') %>
<% end %>
In that case, you just have to pass the options to fb_connect_async_js:
<%= fb_connect_async_js :channel_url => 'http://blahblah' %>
... rest of the partial ...
If your partial doesn't look like the one above, you should edit your question to post yours (the full one).

RoR+ in rjs add value from prompt to table

in js.rjs file i am shwoing prompt with textbox like
page << "var name = prompt('Enter name:'); "
i want to add the value name to the table names
is it possible to do from rjs
if so please guide me how to do it..
You shouldn't do this back and forwarding with rjs. You're returning javascript to be executed by the client, and you can't get the value back directly unless you embed another AJAX call into the javascript your return.
A better way to do this would be to use a single AJAX call. Use a remote_form_for with a text_field for the user to enter their name into, then POST it to your controller action and store it in the database in the normal fashion.
Something like:
# In your view
<% remote_form_for :user, :url => { :controller => :users, :action => :create } do |f| %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
# In your controller
def create
#user = User.new(params[:user])
#user.save
render :update do |page|
# Return whatever javascript you want here
page << "alert('Created user')"
end
end

Resources