Authenticating to devise - ruby-on-rails

I want to be able to simply determine if a user credentials are correctly supplied in an iOS app I'm creating.
The way I have it setup now is with a sessions_controller.rb that handles and returns a user token. The problem is if I want to still log on through the web (not just a check via curl or similar), it doesn't authenticate and spits out
{"success":false,"message":"Error with your login or password"}
So my question is...how can I do authentication and still keep my web-login operational? Here are my related files. My hope was I could curl to a url such as localhost:3000/auth_checks and get one type of authentication response, and continue to have my users login through localhost:3000/sign_in.
From devise.rb
config.skip_session_storage = [:http_auth, :token_auth]
config.token_authentication_key = :auth_token
From routes.rb
resources :clippings
root to: 'clippings#index'
#devise_for :users
resources :auth_checks
devise_for(:users, :controllers => { :sessions => "sessions" })
resources :posts do
end
From auth_checks_controller.rb
class AuthChecksController < ApplicationController
before_filter :authenticate_user!
# GET /auth_checks
# GET /auth_checks.json
def index
#auth_checks = AuthCheck.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #auth_checks }
end
end
# GET /auth_checks/1
# GET /auth_checks/1.json
def show
#auth_check = AuthCheck.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #auth_check }
end
end
# GET /auth_checks/new
# GET /auth_checks/new.json
def new
#auth_check = AuthCheck.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #auth_check }
end
end
# GET /auth_checks/1/edit
def edit
#auth_check = AuthCheck.find(params[:id])
end
# POST /auth_checks
# POST /auth_checks.json
def create
#auth_check = AuthCheck.new(params[:auth_check])
respond_to do |format|
if #auth_check.save
format.html { redirect_to #auth_check, notice: 'Auth check was successfully created.' }
format.json { render json: #auth_check, status: :created, location: #auth_check }
else
format.html { render action: "new" }
format.json { render json: #auth_check.errors, status: :unprocessable_entity }
end
end
end
# PUT /auth_checks/1
# PUT /auth_checks/1.json
def update
#auth_check = AuthCheck.find(params[:id])
respond_to do |format|
if #auth_check.update_attributes(params[:auth_check])
format.html { redirect_to #auth_check, notice: 'Auth check was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #auth_check.errors, status: :unprocessable_entity }
end
end
end
# DELETE /auth_checks/1
# DELETE /auth_checks/1.json
def destroy
#auth_check = AuthCheck.find(params[:id])
#auth_check.destroy
respond_to do |format|
format.html { redirect_to auth_checks_url }
format.json { head :no_content }
end
end
end

Learned a lot...here's what I ended up doing. If you're in this position, I highly recommend putting in the time (not very much) to do this method. http://www.cocoahunter.com/blog/2013/02/13/restful-api-authentication/
If you're like me, you already have a userbase using the standard devise login structure.
I added this to my routes.rb
namespace :api do
namespace :v1 do
resources :tokens,:only => [:create, :destroy]
end
end
Then created and added tokens_controller.rb inside of controllers/api/v1/ (which I created)
# encoding: utf-8
class Api::V1::TokensController < ApplicationController
skip_before_filter :verify_authenticity_token
respond_to :json
def create
email = params[:email]
password = params[:password]
if request.format != :json
render :status=>406, :json=>{:message=>"The request must be json"}
return
end
if email.nil? or password.nil?
render :status=>400,
:json=>{:message=>"The request must contain the user email and password."}
return
end
#user=User.find_by_email(email.downcase)
if #user.nil?
logger.info("User #{email} failed signin, user cannot be found.")
render :status=>401, :json=>{:message=>"Invalid email or passoword."}
return
end
# http://rdoc.info/github/plataformatec/devise/master/Devise/Models/TokenAuthenticatable
#user.ensure_authentication_token!
if not #user.valid_password?(password)
logger.info("User #{email} failed signin, password \"#{password}\" is invalid")
render :status=>401, :json=>{:message=>"Invalid email or password."}
else
render :status=>200, :json=>{:token=>#user.authentication_token}
end
end
def destroy
#user=User.find_by_authentication_token(params[:id])
if #user.nil?
#logger.info(“Token wasnot found.”)
#render :status=>404, :json=>{:message=>”Invalid token.”}
else
#user.reset_authentication_token!
render :status=>200, :json=>{:token=>params[:id]}
end
end
end
That's literally all I had to do. I can now test to this api for authentication from my iOS app. Hope that makes sense to someone out there!

Related

Cannot read property 'all' of undefined with Restangular

I'm working on an application that integrates Rails and AngularJS, and I'm trying to use restangular for all REST functionality, the problem is that when I attempt to post data to create a record I get the error Can not read property 'all' of undefined at Scope.$scope.addPost
The angular controller in which I get the error is this.
poll.controller.js
angular.module('myapp')
.controller('CreatePollCtrl', ['$scope', 'Restangular', function($scope, Restangular) {
$scope.encuesta = {title: "Encuesta docente"};
$scope.addPost = function($scope, Restangular) {
Restangular.all('polls').post($scope.encuesta).then(function() {
});
};
}]);
And what I try is to send a post request to my Rails controller called posts_controller.rb
class PollsController < ApplicationController
before_action :set_poll, only: [:show, :edit, :update, :destroy]
# GET /polls
# GET /polls.json
def index
#polls = Poll.all
end
# GET /polls/1
# GET /polls/1.json
def show
end
# GET /polls/new
def new
#poll = Poll.new
end
# GET /polls/1/edit
def edit
end
# POST /polls
# POST /polls.json
def create
#poll = Poll.new(poll_params)
respond_to do |format|
if #poll.save
format.html { redirect_to #poll, notice: 'Poll was successfully created.' }
format.json { render :show, status: :created, location: #poll }
else
format.html { render :new }
format.json { render json: #poll.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /polls/1
# PATCH/PUT /polls/1.json
def update
respond_to do |format|
if #poll.update(poll_params)
format.html { redirect_to #poll, notice: 'Poll was successfully updated.' }
format.json { render :show, status: :ok, location: #poll }
else
format.html { render :edit }
format.json { render json: #poll.errors, status: :unprocessable_entity }
end
end
end
# DELETE /polls/1
# DELETE /polls/1.json
def destroy
#poll.destroy
respond_to do |format|
format.html { redirect_to polls_url, notice: 'Poll was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_poll
#poll = Poll.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def poll_params
params[:poll]
end
end
Just to show you that the routes are correct:
Is there anything else I should do?
Well, it was totally ok, I just had to remove $scope and Restangular as argument of the function below $scope.encuesta and it worked perfectly D;

How can I get content from website using httparty?

I want to grab content from a website, that I input into a submit form, and store that info as a json I can save to my db. I am trying to use HTTParty, but I'm not quite sure how to implement it to grab the data. Here is what I have so far.
controller
class UrlsController < ApplicationController
before_action :set_url, only: [:show, :edit, :update, :destroy]
#require "addressable/uri"
#Addressable::URI.parse(url)
# GET /urls
# GET /urls.json
def index
#urls = Url.all
end
# GET /urls/1
# GET /urls/1.json
def show
end
# GET /urls/new
def new
#url = Url.new
end
# GET /urls/1/edit
def edit
end
def uri?(string)
uri = URI.parse(string)
%w( http https ).include?(uri.scheme)
rescue URI::BadURIError
false
rescue URI::InvalidURIError
false
end
# POST /urls
# POST /urls.json
def create
#url = Url.new(url_params)
#app_url = params[:url]
respond_to do |format|
if #url.save
format.html { redirect_to #url, notice: 'Url was successfully created.' }
format.json { render action: 'show', status: :created, location: #url }
wordcount
else
format.html { render action: 'new' }
format.json { render json: #url.errors, status: :unprocessable_entity }
end
end
end
def wordcount
# Choose the URL to visit
#app_url = #url
#words = HTTParty.get(#app_url)
# Trick to pretty print headers
#wordcount = Hash[*#words]
end
# PATCH/PUT /urls/1
# PATCH/PUT /urls/1.json
def update
respond_to do |format|
if #url.update(url_params)
format.html { redirect_to #url, notice: 'Url was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #url.errors, status: :unprocessable_entity }
end
end
end
# DELETE /urls/1
# DELETE /urls/1.json
def destroy
#url.destroy
respond_to do |format|
format.html { redirect_to urls_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_url
#url = Url.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def url_params
params.require(:url).permit(:url)
end
end
That is my controller.rb. I am getting a 'bad argument (expected URI object or URI string)' from the line #words = HTTParty.get(#app_url) I need to change what url is put into the form to a valid URL, grab the content I want from that URL, and save that information.
Try something like this:
response = HTTParty.get('https://google.com')
puts response.body, response.code, response.message, response.headers.inspect
To answer your question you can implement the following method, make a new class or put it in a helper.
Might need to include HTTParty
def url_getter(url)
HTTParty.get(url)
end
and call it:
url_getter(#app_url)

Association not recognized, undefined method error

I created 2 scaffolds 'mepager' and 'pimp' and linked the models like this:
class Mepager < ActiveRecord::Base
belongs_to :pimp
end
class Pimp < ActiveRecord::Base
has_one :mepager
end
I added following lines to my routing:
resources :pimps do
resources :mepagers
end
And my mepager create action looks like this:
def create
#mepager = #pimp.build_mepager(mepager_params)
respond_to do |format|
if #mepager.save
format.html { redirect_to #mepager, notice: 'Mepager was successfully created.' }
format.json { render action: 'show', status: :created, location: #mepager }
else
format.html { render action: 'new' }
format.json { render json: #mepager.errors, status: :unprocessable_entity }
end
end
end
And for #pimp to set
def setPimp
#pimp = Pimp.find_by_id(:pimp_id)
end
But if I try to create a new mepager at pimps/1/mepagers/new I get an undefined method build_mepager error.
undefined method `build_mepager' for nil:NilClass
I tried the same in the rails console and it worked with just that method. So I guess somethings still missing to make it work on my web application.
Btw I m using rails 4.0.0
Regards!
Routing
Prefix Verb URI Pattern Controller#Action
pimps GET /pimps(.:format) pimps#index
POST /pimps(.:format) pimps#create
new_pimp GET /pimps/new(.:format) pimps#new
edit_pimp GET /pimps/:id/edit(.:format) pimps#edit
pimp GET /pimps/:id(.:format) pimps#show
PATCH /pimps/:id(.:format) pimps#update
PUT /pimps/:id(.:format) pimps#update
DELETE /pimps/:id(.:format) pimps#destroy
root GET / pimps#index
pimp_mepagers GET /pimps/:pimp_id/mepagers(.:format) mepagers#index
POST /pimps/:pimp_id/mepagers(.:format) mepagers#create
new_pimp_mepager GET /pimps/:pimp_id/mepagers/new(.:format) mepagers#new
edit_pimp_mepager GET /pimps/:pimp_id/mepagers/:id/edit(.:format) mepagers#edit
pimp_mepager GET /pimps/:pimp_id/mepagers/:id(.:format) mepagers#show
PATCH /pimps/:pimp_id/mepagers/:id(.:format) mepagers#update
PUT /pimps/:pimp_id/mepagers/:id(.:format) mepagers#update
DELETE /pimps/:pimp_id/mepagers/:id(.:format) mepagers#destroy
GET /pimps(.:format) pimps#index
POST /pimps(.:format) pimps#create
GET /pimps/new(.:format) pimps#new
GET /pimps/:id/edit(.:format) pimps#edit
GET /pimps/:id(.:format) pimps#show
PATCH /pimps/:id(.:format) pimps#update
PUT /pimps/:id(.:format) pimps#update
DELETE /pimps/:id(.:format) pimps#destroy
Altered line in pimp controller
def create
#pimp = Pimp.new(pimp_params)
respond_to do |format|
if #pimp.save
format.html { redirect_to new_pimp_mepager_path, notice: 'Product Improvement was successfully created.' }
format.json { render action: 'show', status: :created, location: #pimp }
else
format.html { render action: 'new' }
format.json { render json: #pimp.errors, status: :unprocessable_entity }
end
end
end
mepager controller
class MepagersController < ApplicationController
before_action :set_mepager, only: [:show, :edit, :update, :destroy]
def setPimp
#pimp = Pimp.find(params[:pimp_id])
end
# GET /mepagers
# GET /mepagers.json
def index
#mepagers = Mepager.all
end
# GET /mepagers/1
# GET /mepagers/1.json
def show
end
# GET /mepagers/new
def new
#mepager = Mepager.new
end
# GET /mepagers/1/edit
def edit
end
# POST /mepagers
# POST /mepagers.json
def create
raise params[:pimp_id].inspect
#mepager = #pimp.build_mepager(mepager_params)
respond_to do |format|
if #mepager.save
format.html { redirect_to #mepager, notice: 'Mepager was successfully created.' }
format.json { render action: 'show', status: :created, location: #mepager }
else
format.html { render action: 'new' }
format.json { render json: #mepager.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /mepagers/1
# PATCH/PUT /mepagers/1.json
def update
respond_to do |format|
if #mepager.update(mepager_params)
format.html { redirect_to #mepager, notice: 'Mepager was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #mepager.errors, status: :unprocessable_entity }
end
end
end
# DELETE /mepagers/1
# DELETE /mepagers/1.json
def destroy
#mepager.destroy
respond_to do |format|
format.html { redirect_to mepagers_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_mepager
#mepager = Mepager.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def mepager_params
params.require(:mepager).permit(:pre, :post, :comment, :save_h, :save_c, :save_other, :save_otherv, :affect_design, :affect_stress, :affect_me, :affect_other, :affect_dno, :affect_mid, :affect_otherdoc, :owner, :pps, :reference)
end
end
The problem is probably here:
#pimp = Pimp.find_by_id(:pimp_id)
what you are doing is finding a pimp that has an id of the literal symbol :pimp_id (which is highly unlikely to exist)
Probably what you want is the parameter: params[:pimp_id]
EDIT:
and for the second part.
for the create action to work with a real #pimp (that can be found by :pimp_id), you must also do the same on the new action too!
Otherwise create won't work.
Can I recommend something like...
before_action :fetch_pimp, only: [:new, :create]
# GET /mepagers/new
def new
#mepager = Mepager.new
end
# POST /mepagers
# POST /mepagers.json
def create
#mepager = #pimp.build_mepager(mepager_params)
respond_to do |format|
# as previously...
end
end
# ...
private
def fetch_pimp
#pimp = Pimp.find(params[:pimp_id])
end

Rails before_filter doesn't hit database

In my application, I want to only allow user with admin privilege to access this model. So I set up and before_filter to check if the user is an Admin. The problem with this approach is that, after the admin user passes the filter, s/he won't be able to get redirect to the action. Instead, only the views are rendered, which leads to the undefined method each' for nil:NilClass error. What am I doing wrong here?
class TidbitsController < ApplicationController
before_filter :is_admin?
layout "tidbits"
# GET /tidbits
# GET /tidbits.json
protected
def is_admin?
unless current_user.admin?
flash[:error] = "You are not authorized!"
redirect_to "/" and return
end
end
def index
#tidbits = Tidbit.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #tidbits }
end
end
# GET /tidbits/1
# GET /tidbits/1.json
def show
#tidbit = Tidbit.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #tidbit }
end
end
# GET /tidbits/new
# GET /tidbits/new.json
def new
#tidbit = Tidbit.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #tidbit }
end
end
# GET /tidbits/1/edit
def edit
#tidbit = Tidbit.find(params[:id])
end
# POST /tidbits
# POST /tidbits.json
def create
#tidbit = Tidbit.new(params[:tidbit])
respond_to do |format|
if #tidbit.save
format.html { redirect_to #tidbit, notice: 'Tidbit was successfully created.' }
format.json { render json: #tidbit, status: :created, location: #tidbit }
else
format.html { render action: "new" }
format.json { render json: #tidbit.errors, status: :unprocessable_entity }
end
end
end
# PUT /tidbits/1
# PUT /tidbits/1.json
def update
#tidbit = Tidbit.find(params[:id])
respond_to do |format|
if #tidbit.update_attributes(params[:tidbit])
format.html { redirect_to #tidbit, notice: 'Tidbit was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #tidbit.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tidbits/1
# DELETE /tidbits/1.json
def destroy
#tidbit = Tidbit.find(params[:id])
#tidbit.destroy
respond_to do |format|
format.html { redirect_to tidbits_url }
format.json { head :no_content }
end
end
end
in your example all your action methods are protected so maybe that's the problem?
I think you forgot to add the devise required callback filter
before_filter :authenticate_user!
before_filter :is_admin?

Routing in Rails making the Username an URL:

In my Rails App there is Device Model - User, and a Registry model( Each user has one registry).
I wanted to change my routes so that instead of:
"http://localhost:3000/registries/3"
it shows:
"http://localhost:3000/erinwalker"
So I changed routes to
match '/:name' => "registries#show"
And the show action in my controller to:
def show
#user = current_user
#user = User.find_by_name!(params[:name])
#registry = #user.registry
And it works, but when I create or update the registry now first it says:
Couldn't find User with name =
app/controllers/registries_controller.rb:21:in `show'
Even though the show action works?
The registries controller:
class RegistriesController < ApplicationController
before_filter :authenticate_user!, :except => :show
load_and_authorize_resource
# GET /registries
# GET /registries.json
def index
#registries = Registry.all
#user = current_user
respond_to do |format|
format.html # index.html.erb
format.json { render json: #registries }
end
end
# GET /registries/1
# GET /registries/1.json
def show
#user = current_user
#user = User.find_by_name!(params[:name])
#registry = #user.registry
respond_to do |format|
format.html # show.html.erb
format.json { render json: #registry }
end
end
# GET /registries/new
# GET /registries/new.json
def new
#registry = Registry.new
#user = current_user
respond_to do |format|
format.html # new.html.erb
format.json { render json: #registry }
end
end
# GET /registries/1/edit
def edit
#registry = Registry.find(params[:id])
#user = current_user
end
# POST /registries
# POST /registries.json
def create
#registry = current_user.build_registry(params[:registry])
#user = current_user
respond_to do |format|
if #registry.save
format.html { redirect_to #registry, notice: 'Registry was successfully created.' }
format.json { render json: #registry, status: :created, location: #registry }
else
format.html { render action: "new" }
format.json { render json: #registry.errors, status: :unprocessable_entity }
end
end
end
# PUT /registries/1
# PUT /registries/1.json
def update
#registry = Registry.find(params[:id])
#user = current_user
respond_to do |format|
if #registry.update_attributes(params[:registry])
format.html { redirect_to #registry, notice: 'Registry was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #registry.errors, status: :unprocessable_entity }
end
end
end
All my Routes:
Mystorkparty::Application.routes.draw do
devise_for :users
resources :registries
root :to => "static_pages#home"
match '/home', to: 'static_pages#home'
match '/:name' => "registries#show"
When you create or update your models, you send POST /registries or PUT /registries/1.
But /registries is matched by your last rule match '/:name' => "registries#show", so the request hits the show action.
If you run rake routes you should see something like this:
POST /registries(.:format) registries#create
PUT /registries/:id(.:format) registries#update
DELETE /registries/:id(.:format) registries#destroy
/:name(.:format) registries#show
You can add method parameter to your route, so that it will hit show only on GET request.
match '/:name' => "registries#show", :via => :get
But there are still can be collisions in the future. For example, if you have registry name users.
So, it's commonly suggested to use prefixes (match '/r/:name') or define set of allowed names, or choose safe names for registries.
P.S. I don't think load_and_authorize_resource will work for your show action by default. Because it expects params[:id] to load the resource automatically.

Resources