I'm trying to implement sessions in my login process, but the session is not being passed from route to route while I'm using set :session_secret, SecureRandom.hex(64), but if I use set :session_secret, "secret" it works fine.
From my understanding I am not supposed to do that because it is not very secure.
Is there a way to use set :session_secret, SecureRandom.hex(64 and have it pass from route to route? Or, do I have to use set :session_secret, "secret"?
class MainController < Sinatra::Base
register Sinatra::ActiveRecordExtension
enable :sessions
#set :session_secret, SecureRandom.hex(64)
#set :session_secret, "secret"
#set :session_secret, "secretsession"
set :session_secret, "f650ed69344bab0084199bb8cc9aa5a1bd6756c3b57ad67023255af0fc3795057e"
set :views, Proc.new { File.join(root, "../views/") }
get '/sessions_set' do
session[:foo] = 'hello'
if session[:foo] == 'hello'
binding.pry
redirect '/fetch'
else
"Session value has not been set!"
end
end
get '/fetch' do
binding.pry
"You did it! session[:foo] value: #{session[:foo]}.\nMove on to Part II of this lab at '/second_exercise' "
end
end
If you run this every time it will create a different random code every time, making your session unusable essentially. You will have to run this piece of code at startup somehow for it to work.
:session_secret, SecureRandom.hex(64)
For a quick fix you could run this code in a console and just paste the output into your file as it seems you have already done. For a more secure way you could look into using environment variables.
Related
I am very confused with how to provide the default_url_options. I am getting this error
Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
I am using spreecommerce which uses devise for authentication. This error is occurring durring password reset on my development environment. I have not tested it in a production environment yet.
I am using this in my environments/development
config.default_url_options = { host: 'localhost:3000' }
Rails.application.routes.default_url_options[:host] = 'localhost:3000'
in my rails console when I do Rails.application.routes.default_url_options I get {:host => Rails.application.config.domain}. The same thing happends when I do Rails.applicaiton.default_url_options
None of the solutions I have found have worked.
TL;DR In my case Spree::Store.current vanished - I had to recreate it.
I tried set default_url_options for routes and into environments. But with no luck.
So I got into spree_auth_devise-3.1.0 gem source code:
#confirmation_url = spree.spree_user_confirmation_url(:confirmation_token => token, :host => Spree::Store.current.url)
So for the host, it's using Spree::Store. Then I went into console and got that my Spree::Store.current is empty:
(byebug) Spree::Store.current.url
nil
So simply creating a store with dummy data resolved my problem.
store = Spree::Store.new
store.name = 'test'
store.url = 'http://localhost:3000'
store.code = 'spree'
store.default = true
store.save
While in the Rails development environment, I am attempting to add a Sinatra app as a middleware. The Sinatra app uses the geoip gem that processes a user's ip address and returns json with their city.
I can view the returned json by going directly to the example url in the browser or using curl in the command line, http://local.fqdn.org/geoip/locate.json?ip=24.18.211.123. However when I attempt to call the url with wget from within a Rails controller, the Rails app stops responding often crashing my browser and my rails server wont exit using the control+C command.
Any clue to what is happening here? Why would going directly to the url in the browser return the proper response but my call in the controller results in a Time Out?
sinatra-geoip.rb
require 'sinatra'
require 'geoip'
require 'json'
# http://localhost/geoip/locate.json?ip=24.18.211.123
#
# {
# latitude: 47.684700012207
# country_name: "United States"
# area_code: 206
# city: "Seattle"
# region: "WA"
# longitude: -122.384803771973
# postal_code: "98117"
# country_code3: "USA"
# country_code: "US"
# dma_code: 819
# }
class GeoIPServer < Sinatra::Base
get '/geoip/locate.json' do
c = GeoIP.new('/var/www/mywebsite.org/current/GeoLiteCity.dat').city(params[:ip])
body c.to_h.to_json
end
end
routes.rb
mount GeoIPServer => "/geoip"
config/environments/development.rb
Website::Application.configure do
require "sinatra-geoip"
config.middleware.use "GeoIPServer"
...
end
controller
raw_geo_ip = Net::HTTP.get(URI.parse("http://#{geoip_server}/geoip/locate.json?ip=#{request.ip}"))
#geo_ip = JSON.parse(raw_geo_ip)
Our solution was difficult to find. We ended up finding a method in the sinatra source code call forward.
new sinatra-geoip.rb
class GeoIPServer < Sinatra::Base
if defined?(::Rails)
get '/properties.json' do
env["geo_ip.lookup"] = geo_ip_lookup(request.ip)
forward
end
end
def geo_ip_lookup(ip = nil)
ip = ip.nil? ? params[:ip] : ip
result = GeoIP.new('/var/www/mywebsite.org/current/GeoLiteCity.dat').city(ip)
result.to_h.to_json
end
end
Essentially, we removed the /geoip/locate.json route from the file and converted it to a simple method. We needed the geoip lookup to occur when the properties.json was being called, so a new param was added with the geoip information. Then we set the new param equal to #geo_ip variable in the controller.
New properties controller
if Rails.env.development? or Rails.env.test?
# Retrieves param set by sinatra-geoip middleware.
#geo_ip = JSON.parse(env["geo_ip.lookup"] || "{}")
else
# Production and staging code
end
Rather obscure problem and solution. Hopefully it will help someone out there. Cheers.
I'm having a really weird problem with my rails app and facebook's open graph beta. Whenever I post an action to an object, Facebook returns an error that seems to indicate the URL of the object can't be reached, or the og scraper isn't scraping the URL correctly.
However, when I take the URL the app is generating for the post to Facebook and manually use the HTTParty gem to post it, it works.
Here's my code:
class Post < ActiveRecord::Base
FB_CONFIG = YAML.load_file("#{Rails.root}/config/initializers/facebook.yml")[Rails.env]
def self.to_facebook_og(obj, obj_id, verb, auth, extra)
#requires that a user has granted `publish_actions`
found_obj = obj.classify.constantize.find(obj_id) #find the actual object we're talking about
post_url = self.construct_facebook_action_url(obj, found_obj, verb, auth, extra) #create the URL
begin
ret = HTTParty.post(post_url)
logger.info "Facebook Post Action Response = #{ret}"
rescue HTTParty::ResponseError => e #handle any errors
logger.error {"FACEBOOK Response #{ret.code} / #{e.inspect}"}
flash.alert {"There was a Facebook problem. Please try again."}
return
end
end
def self.construct_facebook_action_url(obj, found_obj, verb, auth, extra)
base = 'https://graph.facebook.com/'
uid = auth.uid
namespace = FB_CONFIG['namespace']
token = "?access_token=#{auth.token}"
og_url = "#{obj}=http://theshortestfiction.com/#{obj.pluralize}/#{found_obj.id}"
fb_url = base + uid + '/' + namespace + ':' + verb + token + '&' + og_url + extra
logger.info fb_url
fb_url
end
def self.lint_og_object(obj_url)
lint_ret = HTTParty.post("https://developers.facebook.com/tools/lint/?url=#{obj_url}&format=json")
logger.info "Facebook Linter Response = #{lint_ret}"
end
end
When an object is read via its controller's show method, the app calls Post.to_facebook. From my logs, I can see that that Post.construct_facebook_action_url is constructing the proper url (because like I said, I can pull the URL from the logs and manually post it from the console). So, I'm assuming there's so problem with how I'm passing the URL to HTTParty? Facebook seems able to tell what object URL it should be looking at. Why does the code I've written not work, but manually in the console, it does?
Even weirder -- once there's been a sucessful post action on the object once, the code seems to work consistently. Facebook insists the problem is that the objects' URLs aren't reachable, but I can't understand how they're not, since I can browse to them.
I think this is actually a timeout issue.
I had the exact same issue as you, using HTTParty and getting the URL can't be reached error.
I moved the code to a background process using Resque and it fixed the problem.
I have a method in a model that interacts with an external video encoding service (Zencoder). It uses the zencoder_rb gem. https://github.com/zencoder/zencoder-rb
class EncodingRequest
def check_encoding_status
response = Zencoder::Job.details(self.request_id)
if response.success?
# do something
else
# do something else
end
end
end
The Zencoder::Job#details method makes a call to the Zencoder web service to find out if the video encoding is complete.
The question is how can I hijack the Zencoder::Job#details method so when it is called by check_encoding_status it will return an object that I can craft. The plan is to make that object respond to #success? in whatever way makes sense for my test.
So here's how I'd like the spec to look
it "should mark the encoding as failed if there was an error in Zencoder" do
dummy_response = Zencoder::Response.new(:body => {:state => "finished"}, :code => 200)
# code that will force Zencoder::Job#details to return this dummy_response
#encoding = EncodingRequest.new(:source_asset => #final_large, :target_asset => #final_small)
#encoding.check_encoding_status
#encoding.status.should eql "success"
end
I am currently using rspec 2.5.
I read a bit about mocks and stubs, but I am not sure it's possible to use them in this scenario.
Your help is much appreciated.
Zencoder::Job.stub_chain(:details, :success).and_return(true)
I need to pass the url for each post into user model so it can be shared to twitter. Right now I can pass attributes of the post, such as title and content, which is shared to twitter, but I can't seem to figure out how to pass the post url. Thanks in advance.
post.rb
after_commit :share_all
def share_all
if user.authentications.where(:provider => 'twitter').any?
user.twitter_share(self)
end
end
user.rb
def twitter_share(post)
twitter.update("#{post.title}, #{post.content}") #<--- this goes to twitter feed
end
I haven't tried or tested it but I guess you can do something like:
def share_all
if user.authentications.where(:provider => 'twitter').any?
user.twitter_share(title, content, post_url(self, :host => "your_host"))
end
end
Prior to that, in your model add this:
include ActionController::UrlWriter
This will make the url helper available in your model as well. You can read this to get more information about it.
Please try this as well (found it on this page again):
Rails.application.routes.url_helpers.post_url(self, :host => "your_host")
[EDIT]
I have just read your gist, what you should do is this instead:
## posts.rb
after_commit :share_all
def share_all
# note that I am using self inside the method not outside it.
url = Rails.application.routes.url_helpers.post_url(self, :host => "localhost:3000")
if user.authentications.where(:provider => 'twitter').any?
user.twitter_share(url)
end
end
Or:
include ActionController::UrlWriter #very important if you use post_url(..) directly
after_commit :share_all
def share_all
# if you use the url helper directly you need to include ActionController::UrlWriter
url = post_url(self, :host => "localhost:3000")
if user.authentications.where(:provider => 'twitter').any?
user.twitter_share(url)
end
end
It is very important that you get that url inside the share_all method and not outside it, because self has not the same value whether it's inside or outside. When it's inside the method, self references the instance of Post on which the share_all method is called. When it's outside it's the class Post itself.
I have tested those two variants and they work just well :).