how to use session in sinatra post request? - ruby

I am setting session in "/login" post request so when i trying to access that session in other api the session value will be nil.
post '/login', :provides => :json do
params = JSON.parse(request.env["rack.input"].read)
uname = params["username"]
session[:username] = random_string
return session[:username]
end
get '/list' do
puts session[:username]
end
"/list" call print "nil" in command line
What is the solution to use that session outside this post request once it set by "/login"?

Related

token refresh callback access token in Box using oauth2.0 using ruby

I'm new to Box Api and ruby. I am trying trying refreshing token, but I'm not sure about what is token_refresh_callback in the below code
client = Boxr::Client.new('zX3UjFwNerOy5PSWc2WI8aJgMHtAjs8T',
refresh_token: 'dvfzfCQoIcRi7r4Yeuar7mZnaghGWexXlX89sBaRy1hS9e5wFroVVOEM6bs0DwPQ',
client_id: 'kplh54vfeagt6jmi4kddg4xdswwvrw8y',
client_secret: 'sOsm9ZZ8L8svwrn9FsdulLQVwDizKueU',
&token_refresh_callback)
Also, once my access token is expired, does this method revoke the token?
Thanks for the help!
Using the Access and Refresh Tokens
The access_token is the actual string needed to make API requests.Each access_token is valid for 1 hour.In order to get a new, valid token, you can use the accompanying refresh_token.Each refresh_token is valid for one use in 60 days.Every time you get a new access_token by using a refresh_token,
we reset your timer for the 60 day period and hand you a new refresh_token.
This means that as long as your users use your application once every 60 days, their login is valid forever.
In box_api_controller.rb file
def make_request
#Check access token expire or not.
check_access_token_expire = check_access_token_expire_dt
if check_access_token_expire.split("-")[0] == "access_token"
#Create client by passing Token
#box_client = Boxr::Client.new(check_access_token_expire.split("-")[1])
cookies[:token] = check_access_token_expire.split("-")[1]
else
if check_access_token_expire.split("-")[0] == "refresh_token"
#Call method
create_post_req_url("refresh_token","refresh_token",check_access_token_expire.split("-")[1])
else
# kick off authorization flow
parameters = "response_type=code&client_id=<your client id>&redirect_uri=<your application url>/handle_user_decision/&state=security_token"
url = "https://account.box.com/api/oauth2/authorize?#{parameters}"
redirect_to url
end
end
end
After authorized the client id, get code in response
def handle_user_decision
# kick off authorization flow
#Get authorization code
code_url = Rack::Utils.parse_query URI(request.original_url).query
code = code_url["code"]
#Call method
create_post_req_url("authorization_code","code", code)
end
Create Post Url
def create_post_req_url(grant_type,header, code)
#Set oauth2 url
uri = URI.parse("https://api.box.com//oauth2//token")
#Passing parameter
data = "grant_type=#{grant_type}&#{header}=#{code}&client_id=<your client id>&client_secret=<your client secret key>"
#Set header
headers = {"Content-Type" => "application/x-www-form-urlencoded"}
#Get http request
http = Net::HTTP.new(uri.host,uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
#Do post the URL
response = http.post(uri.path,data.to_s,headers)
#Check response
if response.code != "200"
flash[:alert] =":#{response.code} #{JSON.parse(response.body)}"
else
#flash[:alert] ="#{response.body.to_json}"
parsed = JSON.parse(response.body) # returns a hash
token = parsed["access_token"]
cookies[:token] = nil
cookies[:token] = token
if grant_type == "authorization_code"
#Insert BOX access token details
user = "<your drive user name>"
insert_access_token(user, token, parsed["refresh_token"], Time.now)
else
if grant_type == "refresh_token"
#Update BOX access token
updt_access_token(user, token, code, parsed["refresh_token"], Time.now)
end
end
redirect_to box_api_index_path
end
end
Check access token expire or not
def check_access_token_expire_dt
#access_token_time = BoxApiAccessToken.getaccesstokentime
if !#access_token_time.blank?
#access_token_time.each do |token_details |
if token_details.access_token_dt != nil
if token_details.new_access_token_dt.to_datetime.new_offset(Rational(9, 24)).strftime('%Y/%m/%d %H:%M') < Time.now.to_datetime.new_offset(Rational(9, 24)).strftime('%Y/%m/%d %H:%M')
check_access_token_expire_dt = "refresh_token-#{token_details.refresh_access_token}"
return check_access_token_expire_dt
else
check_access_token_expire_dt = "access_token-#{token_details.access_token}"
return check_access_token_expire_dt
end
else
check_access_token_expire_dt = "new_token-req_new_token"
return check_access_token_expire_dt
end
end
else
check_access_token_expire_dt = "new_token-req_new_token"
return check_access_token_expire_dt
end
end
In Model
def insert_access_token(user,access_token,refresh_access_token,access_token_dt)
#box_access_token = BoxApiAccessToken.new(
:user => user,
:access_token => access_token,
:refresh_access_token => refresh_access_token,
:access_token_dt => access_token_dt)
#Save User Device Data
#box_access_token.save
end
#Update access_token,refresh_access_token,access_token_dt details in DB
def updt_access_token(user,access_token, refresh_access_token,new_refresh_access_token,access_token_dt)
##box_access_token_updt = BoxApiAccessToken.find_refresh_access_token(refresh_access_token)
#box_access_token_updt = BoxApiAccessToken.find_by_refresh_access_token(refresh_access_token)
attributes = {:access_token => access_token,:access_token_dt => access_token_dt, :refresh_access_token => new_refresh_access_token, :updated_at => access_token_dt}
#Update the object
#box_access_token_updt.update_attributes(attributes)
end
In index.html.erb
<%= form_tag(:controller => "box_api", :action => 'make_request') do |f| %>
<div class="form-group"><%= submit_tag("Box Login", class: "btn btn-primary") %></div><% end %>
I just want to want to request an access token and then after it expires refresh it using refresh token and cycle. How do you think i can do it?

Mocking a post request with binary data in Sinatra

I have an endpoint in my Sinatra application that will be receiving binary data as part of the body. The other application sending it data will have a Faraday request that looks like this:
connection = Faraday.new(url: "https://example.com/post_data") do |conn|
conn.request :multipart
conn.adapter :net_http
conn.headers['Content-Type'] = 'octet/stream'
end
#response ||= connection.post do |req|
req.params = { :host => host,
:verification => "false"}
req.body = my_base64_encoded_binary
end
Then, in Sinatra, I will have an endpoint that receives those request parameters and binary data and passes it along to a model, like so:
post '/post_data' do
request.body.rewind
payload = request.body.read
raise Sinatra::NotFound unless payload and params[:host]
output = MyOutput.new(params, payload)
content_type 'application/json'
body output.data
end
When I try to test this endpoint using Rack::Test helpers, I end up in a weird situation. I can't seem to create the proper mock in order to test this endpoint properly. Based on some manual testing with PostMan, I'm pretty certain my endpoint works properly. It's just the test that's holding me up. Here is the spec:
it "should return a json response" do
post(url, :host => host, :verification => "false") do |req|
req.body = [my_binary]
req.content_type = "application/octet-stream"
end
expect(last_response.status).to eq(200)
expect(last_response.content_type).to eq("application/json")
end
And when I inspect what the incoming request looks like in the test, it does not contain a proper body. params is properly set to the host and verification settings I set, but the body is also being set to the params (inspected through payload = request.body.read) instead of the binary.
Is there a different way to set up the mock so that the binary properly is set to the body of the request, and the parameters are still set to the request parameters properly?
The answer is that the only way to post the body is where I was adding the params in the rack test helper. I needed to take the params and move them into the query string of the URL in the request, and then only add the binary as the body of the post request in the test helper.
let(:url) { "http://example.com/post_data?host=>#{host}&verification=#{verification}" }
it "should return a json response" do
post(url, my_binary)
expect(last_response.status).to eq(200)
expect(last_response.content_type).to eq("application/json")
end

Ruby HTTP sending API key Basic_auth

I have been following a tutorial on GitHub Pages and
I am trying to pass an Apikey to a webservice as basic auth 'apiKey' => 'huda7da97hre3rhr1yrh0130409u1u' for example but I cannot work out how to implement it into the method, or even if that is the proper place for it.
I have a class called connection with my request method in it. I need to post 'apiKey' as header and not in the body. I have read the ruby docs but I cannot work out how to apply it to this specific class.
require "net/http"
require "uri"
require "ostruct"
require "json"
class Connection
ENDPOINT = "http://localhost"
APP_LOCATION = "/task_manager/v1/"
VERB_MAP = {
:get => Net::HTTP::Get,
:post => Net::HTTP::Post,
:put => Net::HTTP::Put,
:delete => Net::HTTP::Delete
}
def initialize(endpoint = ENDPOINT)
uri = URI.parse(endpoint)
#http = Net::HTTP.new(uri.host, uri.port)
end
def get(path, params)
request_json :get, path, params
end
def post(path, params)
request_json :post, APP_LOCATION + path, params
end
def put(path, params)
request_json :put, path, params
end
def delete(path, params)
request_json :delete, path, params
end
private
def request_json(method, path, params)
response = request(method, path, params)
body = JSON.parse(response.body)
OpenStruct.new(:code => response.code, :body => body)
rescue JSON::ParserError
response
end
def request(method, path, params = {})
case method
when :get
full_path = encode_path_params(path, params)
request = VERB_MAP[method.to_sym].new(full_path)
else
request = VERB_MAP[method.to_sym].new(path)
request.set_form_data(params)
end
#http.request(request)
end
def encode_path_params(path, params)
encoded = URI.encode_www_form(params)
[path, encoded].join("?")
end
end
If I post to the server using Advanced Rest Client and put the apikey in the
http://localhost/task_manager/v1/tasks?=
header
Authorization: 9c62acdda8fe12507a435345bb9b2338
and in the body
email=free%40mail.com&password=free&task=test
then I get
{
error: false
message: "Task created successfully"
task_id: 5
}
So how can I post it using this class?.
connection = Connection.new
result = connection.post("task", {'task' => 'task'})
Basic Authentication example:
req = Net::HTTP::Get.new(uri)
req.basic_auth 'user', 'pass'
http://docs.ruby-lang.org/en/trunk/Net/HTTP.html#class-Net::HTTP-label-Basic+Authentication
Or if you want to add a raw Authorization header in your request method you can do
request.add_field 'Authorization', 'huda7da97hre3rhr1yrh0130409u1u'
But basic authentication normally means that there is a user name and a password. With your API key - I am not sure you actually need basic authentication. I do not know what you API actually requires but if you have not tried it yet you can try sending the api key as an additional parameter
result = connection.post("register", {'email' => email, 'name' => name, 'password' => password, 'apiKey' => 'huda7da97hre3rhr1yrh0130409u1u' })

AFMotion Post with Token

I've got a Sinatra/Warden Remote API, and a client in RubyMotion.
How can I post the Authentication Token and User Object with AFMotion for initial registration (from client)?
This more or less what I have so far, not much I know.
Basically I need to pass through a token to the remote api and a user object.
def register_user(user)
#client = AFMotion::Client.build("http://localhost:9393/register") do
header "Accept", "application/json"
request_serializer: :json
response_serializer :json
end
end
Help?
You can change the line you initiate #client object to something like this
#client = AFMotion::Client.build("http://localhost:9393/") do
header "Accept", "application/json"
response_serializer :json
end
and when you want to do a POST request, you can do
#client.post('register', {
token: 'TOKEN HERE',
user: 'USER OBJECT HERE'
}) do |result|
puts result
end
You can find out more here.

Error on a Sinatra's middleware

In my Sinatra app, I've created the following middleware to ensure the incoming request contains the parameter "token" in the query string
class CheckMandatoryParams
def initialize(app)
#app = app
end
def call(env)
# Get token from query string
h = Hash[*env["QUERY_STRING"].split('&').map {|s| s.split('=')}.flatten]
token = h["token"]
# Do not authorize request unless both parameters are not null
if token.nil? then
Log.instance.error("CheckMandatoryParams - token not provided")
[401, {"Content-Type" => "text/plain", "Content-Length" => body.length.to_s}, ["Unauthorized"]]
else
Log.instance.debug("CheckMandatoryParams - token provided")
#app.call(env)
end
end
end
In the case the params exists, the next app is calls and everything goes fine.
In the case the params is not in the query string, the response is not sent, I receive a huge html file indicating an error at the line ' [401, {"Content-Type" => "text/plain", "Content-Length" => body.length.to_s}, ["Unauthorized"]]' but I cannot figure out what is wrong.
Any idea?
UPDATE
This is working better like that :)
body = "Unauthorized"
[401, {"Content-Type" => "text/plain", "Content-Length" => body.length.to_s}, [body]]
I did not manage to retrieve the param with the following code though:
request = Rack::Request.new(env)
token = request.params["token"]
It looks like the "body" variable may be undefined. One possible way to rewrite your code would be as follows:
class CheckMandatoryParams
def initialize(app)
#app = app
end
def call(env)
request = Rack::Request.new(env)
token = request.params["token"]
if token.nil?
[401, {"Content-Type" => "text/plain", "Content-Length" => request.body.length.to_s}, ["Unauthorized"]]
else
#app.call(env)
end
end
end

Resources