I am trying to setup json based authentication on my current rails app. The app's authentication is currently handled by devise.
I have read couple of questions on stackoverflow, but I do not seem to get it working.
routes.rb:
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks", :sessions => 'users/sessions' }
SessionsController:
class Users:: SessionsController < Devise::SessionsController
def create
resource = warden.authenticate!(:scope => resource_name, :recall => :failure)
return sign_in_and_redirect(resource_name, resource)
end
def sign_in_and_redirect(resource_or_scope, resource=nil)
scope = Devise::Mapping.find_scope!(resource_or_scope)
resource ||= resource_or_scope
sign_in(scope, resource) unless warden.user(scope) == resource
return render :json => {:success => true, :redirect => stored_location_for(scope) || after_sign_in_path_for(resource)}
end
def failure
return render:json => {:success => false, :errors => ["Login failed."]}
end
end
Not sure where I have gone wrong. The call I am making is:
JSON:
Content-Type: application/json
Accept: application/json
data: {user: {password: mypass, email: some_email#gmail.com}}
The Error:
MultiJson::DecodeError (756: unexpected token at '{user: {password: mypass, email: some_email#gmail.com}}'):
2012-06-30T18:10:10+00:00 app[web.1]: vendor/bundle/ruby/1.9.1/gems/json-1.6.5/lib/json/common.rb:148:in `parse'
If you paste that JSON into http://jsonlint.com, you get the same error.. Instead, you should wrap your values in quotes:
{
"user": {
"password": "mypass",
"email": "some_email#gmail.com"
}
}
Related
Problem Statement
I'm Newbie in Rails and following this tutorial for setting up JWT based authentication in API, and working on an existing web application that uses Devise. My task at the moment is to add a JSON API to the application.
This rails project works fine for a web applications. However, Incase of API I'm getting empty resource while I still have value in params.
Environment
rails (6.1.4)
devise (4.8.0)
devise-jwt (0.9.0)
warden (1.2.9)
warden-jwt_auth (0.6.0)
Controller & Route
app/controllers/api/v1/users/registrations_controller.rb
class Api::V1::Users::RegistrationsController < Devise::RegistrationsController
respond_to :json
skip_before_action :verify_authenticity_token
# POST /resource
def create
super
end
private
def respond_with(resource, _opts = {})
if resource.persisted?
render json: {
status: { code: 200, message: "Signed up sucessfully." },
data: UserSerializer.new(resource).serializable_hash[:data][:attributes]
}
else
render json: {
status: { message: "User couldn't be created successfully. #{resource.errors.full_messages.to_sentence}" }
}, status: :unprocessable_entity
end
end
end
config/routes.rb
# For Web
devise_for :users, controllers: { registrations: "registrations" }
# Authentication
devise_scope :user do
get "/login" => "devise/sessions#new", as: :login
get "/logout" => "sessions#destroy", :as => :logout
get "/signup" => "registrations#new", :as => :signup
scope "my" do
get "profile", to: "registrations#edit"
put "profile/update", to: "registrations#update"
end
end
authenticated :user do
resources :dashboard, only: [:index] do
collection do
get :home
end
end
end
unauthenticated do
as :user do
root to: "devise/sessions#new", as: :unauthenticated_root
end
end
# For API
namespace :api do
namespace :v1 do
devise_for :users, path: '', path_names: {
sign_in: 'login',
sign_out: 'logout',
registration: 'signup'
},
controllers: {
sessions: 'api/v1/users/sessions',
registrations: 'api/v1/users/registrations'
}
end
end
Debugging information
app/controllers/api/v1/users/registrations_controller.rb
| 66: private
| 67: def respond_with(resource, _opts = {})
| 68: byebug
| => 69: if resource.persisted?
| 70: render json: {
| 71: status: { code: 200, message: "Signed up sucessfully." },
| 72: data: UserSerializer.new(resource).serializable_hash[:data][:attributes]
| 73: }
| (byebug) resource
| #<User
id: nil,
email: "",
first_name: "",
last_name: "",
role: "member",
created_at: nil,
updated_at: nil,
jti: nil
>
| (byebug) params
| #<ActionController::Parameters
{
"email"=>"test#test.com",
"first_name"=>"John",
"last_name"=>"Wick",
"password"=>"password",
"controller"=>"api/v1/users/registrations",
"action"=>"create",
"registration"=>{
"email"=>"test#test.com",
"first_name"=>"John",
"last_name"=>"Wick",
"password"=>"password"
}
} permitted: false>
Request
curl -X POST \
http://127.0.0.1:3000/api/v1/signup \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-d '{
"email": "test#test.com",
"first_name": "John",
"last_name": "Wick",
"password": "password"
}'
Response
{
"status": {
"message": "User couldn't be created successfully. Email can't be blank and Password can't be blank"
}
}
I am using recycled code from a project but in this version I am not having good results.
I use Rails 5.2.2 and RVM Ruby 2.7.1
I need to use this function to call an ajax and deliver the already stored data of a client and fill out a form, the data will be searched through the RUN of each client
I don't understand why the match () are not working for me
Controller Pacientes
class Ajax::PacientesController < ApplicationController
layout nil
def obtener_datos_paciente
#usuario = params[:rut]
usuario = Usuario.first :rut => params[:rut]
puts usuario.inspect.yellow
if usuario.nil?
render :json => {
:exito => true,
:mensaje => "No existen registros asociados al rut #{params[:rut]}."
}
else
render :json => {
:exito => true,
:es_empresa => true,
:mensaje => "El paciente con rut #{params[:rut]} ya existe.",
:data => {
:id => usuario.id,
:rut => usuario.rut,
:primer_nombre => usuario.primer_nombre,
:segundo_nombre => usuario.segundo_nombre,
:apellido_paterno => usuario.apellido_paterno,
:apellido_materno => usuario.apellido_materno,
:direccion => usuario.direccion,
:ciudad => usuario.ciudad,
:comuna => usuario.comuna,
:telefono => usuario.telefono,
:email => usuario.email
}
}
end
rescue Excepciones::DatosNoExistentesError => e
flash.now[:info] = e.message
render :json => { :mensaje => e.message }
end
end
Routes
match(
"ajax/pacientes/:rut" => "ajax::pacientes#obtener_datos_paciente",
:as => :obtener_datos_paciente,
:via => :get
)
Controller Usuario
require 'json'
class UsuariosController < ApplicationController
helper_method :url_paciente
def index
#usuarios = Usuario.all
end
def ingreso_paciente
end
def registrar_ingreso
end
def ingresar_ficha_kinesica
alias url_paciente obtener_datos_paciente_ajax_pacientes_path
end
end
The easiest fix would be to rename your controller to:
class PacientesController < ApplicationController and match to "ajax/pacientes/:rut" => "pacientes#obtener_datos_paciente"
If your controller must exist in the Ajax namespace, then it should probably have a namespaced route as well. An example can be found in this answer.
i successfully got generating tokens working on the ios side, and i have a heroku rails app set up. How do i retrieve this token on the server side?
getting the error `Completed 500 Internal Server Error in 1ms (ActiveRecord: 0.0ms)
NoMethodError (undefined method []' for nil:NilClass):
app/controllers/login_controller.rb:11:in 'log_in'
here is my controller code:
class LoginController < ApplicationController
def index
end
def log_in
puts params
headers = {"X-Parse-Application-Id" => "APIKEY",
"X-Parse-REST-API-Key" => "APIKEY"}
query = {:username => params[:user][:username],
:password => params[:user][:password]}
#response = HTTParty.get('https://api.parse.com/1/login',
:query => query,
:headers => headers)
session[:session_token] = #response["sessionToken"]
session[:object_id] = #response["objectId"]
#object_id = session[:object_id]
#test = HTTParty.get("https://api.parse.com/1/classes/_User/#{#object_id}",
:headers => {"X-Parse-Application-Id" => "APIKEY",
"X-Parse-REST-API-Key" =>"APIKEY"} )
session[:stripe_acct_id] = #test["uid"]
end
def logout
logout = HTTParty.post('https://api.parse.com/1/logout',
:headers => {"X-Parse-Application-Id" => "APIKEY",
"X-Parse-REST-API-Key" => "APIKEY",
"X-Parse-Session-Token" => session[:session_token]})
reset_session
redirect_to :controller => "login"
end
def deauthorize
#object_id = session[:object_id]
HTTParty.post("https://connect.stripe.com/oauth/deauthorize",
:basic_auth => { :username => ENV['STRIPE_SECRET'] },
:query => { client_id: ENV['STRIPE_CONNECT_CLIENT_ID'],
stripe_user_id: session[:stripe_acct_id]})
end
end
In your controller add:
protect_from_forgery: :null, only: :log_in
For your error, it's because you don't send user object in your post request.
I'm working on an application where I've had to put together some custom rails parameters for the routes and I keep getting no route found errors when I try to access the page associated with the show method. The application is allowing me to reach my edit pages, so I know it's working on some level but I have to have an error I'm not seeing somewhere that's messing with the normal view. The custom parameters rely on an :identifier that has been custom created for each object. Because the application manages several institutions, all with their objects and files, I've had to right several different sets of routes to handle each different thing. The routes for institutions seem to be working fine, but the second set, for :intellectual_objects are the ones that aren't working.
This is my routes file (irrelevant parts excluded):
Fluctus::Application.routes.draw do
get "institutions/:institution_identifier/objects", to: 'intellectual_objects#index', as: :institution_intellectual_objects, :constraints => { :institution_identifier => /[\w+\.]+/ }
post "institutions/:institution_identifier/objects", to: 'intellectual_objects#create', :constraints => { :institution_identifier => /[\w+\.]+/ }
#Intellectual Object Routes
#get "objects/:institution_identifier", to: 'intellectual_objects#index', as: :institution_intellectual_objects, :constraints => { :institution_identifier => /[\w+\.]+/ }
#post "objects/:institution_identifier", to: 'intellectual_objects#create', :constraints => { :institution_identifier => /[\w+\.]+/ }
patch "objects/:intellectual_object_identifier", to: 'intellectual_objects#update', :constraints => { :intellectual_object_identifier => /[\w+\/\.]+/ }
put "objects/:intellectual_object_identifier", to: 'intellectual_objects#update', :constraints => { :intellectual_object_identifier => /[\w+\/\.]+/ }
delete "objects/:intellectual_object_identifier", to: 'intellectual_objects#destroy', :constraints => { :intellectual_object_identifier => /[\w+\/\.]+/ }
get "objects/:intellectual_object_identifier/edit", to: 'intellectual_objects#edit', as: :edit_intellectual_object, :constraints => { :intellectual_object_identifier => /[\w+\/\.]+/ }
get "objects/:intellectual_object_identifier/events", to: 'events#index', as: :intellectual_object_events, :constraints => { :intellectual_object_identifier => /[\w+\/\.]+/ }
post "objects/:intellectual_object_identifier/events", to: 'events#create', :constraints => { :intellectual_object_identifier => /[\w+\/\.]+/ }
get "objects/:intellectual_object_identifier", to: 'intellectual_objects#show', as: :intellectual_object, :constraints => { :intellectual_object_identifier => /[\w+\/\.]+/ }
#post "objects/institution_identifier/:intellectual_object_identifier/data", to: 'generic_files#create', as: intellectual_object_generic_files, :constraints => { [:intellectual_object_identifier, :institution_identifier] => /[\w+\.]/ }
#patch "objects/institution_identifier/:intellectual_object_identifier/data/:filename", to: 'generic_files#update', :constraints => { [:intellectual_object_identifier, :institution_identifier] => /[\w+\.]/ }
Blacklight.add_routes(self)
mount Hydra::RoleManagement::Engine => '/'
root :to => "catalog#index"
end
This is my IntellectualObject Controller:
class IntellectualObjectsController < ApplicationController
before_filter :authenticate_user!
#load_and_authorize_resource :institution, only: [:index, :create]
load_and_authorize_resource :through => :institution, only: :create
#load_and_authorize_resource except: [:index, :create]
before_filter :set_object, only: [:show, :edit, :update, :destroy]
before_filter :set_institution, only: [:index, :create]
include Aptrust::GatedSearch
apply_catalog_search_params
include RecordsControllerBehavior
self.solr_search_params_logic += [:for_selected_institution]
def update
if params[:counter]
# They are just updating the search counter
search_session[:counter] = params[:counter]
redirect_to :action => "show", :status => 303
else
# They are updating a record. Use the method defined in RecordsControllerBehavior
super
end
end
def destroy
resource.soft_delete
respond_to do |format|
format.json { head :no_content }
format.html {
flash[:notice] = "Delete job has been queued for object: #{resource.title}"
redirect_to root_path
}
end
end
protected
# Override Hydra-editor to redirect to an alternate location after create
def redirect_after_update
intellectual_object_path(resource)
end
def self.cancan_resource_class
CanCan::ControllerResource
end
private
def for_selected_institution(solr_parameters, user_parameters)
#puts "In for_selected_institution------------------------------------------"
#puts params[:institution_identifier]
#puts params[:intellectual_object_identifier]
if(params[:institution_identifier])
institution = Institution.where(desc_metadata__institution_identifier_tesim: params[:institution_identifier]).first
else
io = IntellectualObject.where(desc_metadata__intellectual_object_identifier_tesim: params[:intellectual_object_identifier]).first
institution = io.institution
end
#puts "INSTITUTION: #{institution.id}"
solr_parameters[:fq] ||= []
solr_parameters[:fq] << ActiveFedora::SolrService.construct_query_for_rel(is_part_of: "info:fedora/#{institution.id}")
end
# Override Blacklight so that it has the "institution_identifier" set even when we're on a show page (e.g. /objects/foo:123)
def search_action_url options = {}
institution_intellectual_objects_path(params[:institution_identifier] || #intellectual_object.institution.institution_identifier)
end
def set_institution
if params[:institution_identifier].nil? || Institution.where(desc_metadata__institution_identifier_tesim: params[:institution_identifier]).empty?
redirect_to root_url
flash[:alert] = "Sonething wrong with institution_identifier."
else
#institution = Institution.where(desc_metadata__institution_identifier_tesim: params[:institution_identifier]).first
authorize! [:create, :index], #institution if cannot? :read, #institution
end
end
def set_object
if params[:intellectual_object_identifier].nil? || IntellectualObject.where(desc_metadata__intellectual_object_identifier_tesim: params[:intellectual_object_identifier]).empty?
redirect_to root_url
flash[:alert] = "Something wrong with intellectual_object_identifier."
else
io_options = IntellectualObject.where(desc_metadata__intellectual_object_identifier_tesim: params[:intellectual_object_identifier])
io_options.each do |io|
if params[:intellectual_object_identifier] == io.intellectual_object_identifier
#intellectual_object = io
#institution = #intellectual_object.institution
end
end
if #intellectual_object.nil?
redirect_to root_url
flash[:alert] = "The object you requested does not exist."
end
#authorize! [:show, :edit, :update, :destroy], #institution if cannot? :read, #institution
end
end
end
I'm getting the following error when I try to access the show route (for example: localhost:3000/objects/test.org/126939282):
ActionController::UrlGenerationError in IntellectualObjects#show
Showing /Users/kec6en/HydraApp/fluctus/app/views/intellectual_objects/_facet_limit.html.erb where line #11 raised:
No route matches {:action=>"index", :intellectual_object_identifier=>"columbia.edu/798d6e812041532c", :controller=>"intellectual_objects", :f=>{"institution_name_ssi"=>["Columbia University"]}}
The parameters are showing:
{"intellectual_object_identifier"=>"columbia.edu/798d6e812041532c"}
And I'm getting this error when I run my spec tests on the IntellectualObjectController
Failure/Error: get :show, intellectual_object_identifier: obj1
ActionController::UrlGenerationError:
No route matches {:intellectual_object_identifier=>"kaulkedurgan.org13/39b1eb47-da8b-4145-b03b-5f1851407012", :controller=>"intellectual_objects", :action=>"show"}
I just don't understand because the routes are there, and some of them appear to be working in the application, but every single one is failing in my spec tests. Any and all help is appreciated. Thank you.
Your route to intellectual_objects#index has the constraint that the :institution_identifier should match /[\w+\.]+/, but columbia.edu/798d6e812041532c does not match that regexp. Even when you add \/ to your regexp, I am pretty sure that the slash will confuse Rails routing system.
Perhaps you want to change the route to something like this
get "institutions/:institution_identifier/:some_id/objects",
to: 'intellectual_objects#index',
as: :institution_intellectual_objects,
constraints: { institution_identifier: /[\w+\.]+/ }
And than provide columbia.edu (institution_identifier) and 798d6e812041532c (some_id) as separate values.
According to your error:
No route matches {:action=>"index"
It seems you're trying to access the index action?
Being honest, I couldn't bring myself to look through all your routes (you may want to cut out the irrelevant stuff?)
How are you calling the routes with link_to?
I know we can sync data using rhodes without Rhosync or Rhoconnect by using direct web service, but I'm here little bit confuse where to place that code for webservice call and how do we initialize it. Can anyone help me with small example?
Thanks in Advance.
I got it and it works for me.
class ProductController < Rho::RhoController
include BrowserHelper
# GET /product
def index
response = Rho::AsyncHttp.get(:url => "example.com/products.json",
:headers => {"Content-Type" => "application/json"})
#result = response["body"]
render :back => '/app'
end
# GET /product/{1}
def show
id =#params['id']
response = Rho::AsyncHttp.get(:url => "example.com/products/"+ id +".json",
:headers => {"Content-Type" => "application/json"})
#result = response["body"]
end
# GET /product/new
def new
#product = product.new
render :action => :new, :back => url_for(:action => :index)
end
# GET /product/{1}/edit
def edit
id =#params['product_id'].to_s
response = Rho::AsyncHttp.get(:url => "example.com/products/#{id}.json",
:headers => {"Content-Type" => "application/json"})
#result = response["body"]
end
# POST /product/create
def create
name = #params['product']['name']
price = #params['product']['price']
body = '{"product" : {"name" : "'+ name +'","price" :"'+ price +'" } }'
#result = Rho::AsyncHttp.post(:url => "example.com/products.json",
:body => body, :http_command => "POST", :headers => {"Content-Type" => "application/json"})
redirect :action => :index
end
# POST /product/{1}/update
def update
name=#params['product']['name']
price=#params['product']['price']
body = '{"product" : {"name" : "' + name + '","price" :"' + price + '" } }'
id = #params["product_id"].to_s
response = Rho::AsyncHttp.post(:url => "example.com/products/#{id}.json",
:body => body, :http_command => "PUT",:headers => {"Content-Type" => "application/json"})
redirect :action => :index
end
# POST /product/{1}/delete
def delete
id = #params["product_id"].to_s
response = Rho::AsyncHttp.post(:url => "example.com/products/#{id}.json",
:http_command => "DELETE",
:headers => {"Content-Type" => "application/json"})
redirect :action => :index
end
end
Most easy form of http server request is next:
Rho::AsyncHttp.get(
:url => "http://www.example.com",
:callback => (url_for :action => :httpget_callback)
)
where httpget_callback is name of the controller callback method.
See more details at official Rhodes docs.