Configure APIs using authoring authoring tool

I am trying to get the user registration endpoint setting for my rails application so that I can access the application features in the iOS version. I went ahead, and namespaced my API, and so far have managed to get user authentication using Devise and JWT.

This is great, but I also need the ability to register a user through the API. To be honest, I have no idea how to implement this correctly. Several GOogle servlets call outdated articles , use an outdated token, authenticate , or never respond.

The following is the code that I believe is most relevant to this issue:

routes.rb (section with names for API)

namespace :api do namespace :v1 do devise_for :users, controllers: { registrations: 'api/v1/registrations' } resources :classrooms resources :notifications end end end 

registrations_controller.rb (API contorller)

 class Api::V1::RegistrationsController < Devise::RegistrationsController respond_to :json def create if params[:email].nil? render :status => 400, :json => {:message => 'User request must contain the user email.'} return elsif params[:password].nil? render :status => 400, :json => {:message => 'User request must contain the user password.'} return end if params[:email] duplicate_user = User.find_by_email(params[:email]) unless duplicate_user.nil? render :status => 409, :json => {:message => 'Duplicate email. A user already exists with that email address.'} return end end @user = User.create(user_params) if @user.save! render :json => {:user => @user} else render :status => 400, :json => {:message => @user.errors.full_messages} end end private # Never trust parameters from the scary internet, only allow the white list through. def user_params devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute, :first_name, :last_name, :access_code]) end end 

Registration Endpoint

http://localhost:3000/api/v1/users

Postman Sample Response

 { "message": [ "Email can't be blank", "Password can't be blank", "Access code is invalid [Beta]." ] } 

Any help would be greatly appreciated as I really want to know more (and make it work!).

UPDATE 1

This is what I get on the server after creating a mail request to create a user ...

 Started POST "/api/v1/users" for 127.0.0.1 at 2017-02-22 09:22:11 -0800 Processing by Api::V1::RegistrationsController#create as */* Parameters: {"user"=>{"email"=>" user@sampleapi.com ", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "access_code"=>"uiux"}} User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."email" IS NULL LIMIT $1 [["LIMIT", 1]] Completed 400 Bad Request in 2ms (Views: 0.2ms | ActiveRecord: 0.4ms) 

Updated Registrations_controller

 class Api::V1::RegistrationsController < Devise::RegistrationsController before_action :configure_sign_up_params, only: [:create] respond_to :json def create @user = build_resource(sign_up_params) if @user.persisted? # We know that the user has been persisted to the database, so now we can create our empty profile if resource.active_for_authentication? sign_up(:user, @user) render :json => {:user => @user} else expire_data_after_sign_in! render :json => {:message => 'signed_up_but_#{@user.inactive_message}'} end else if params[:user][:email].nil? render :status => 400, :json => {:message => 'User request must contain the user email.'} return elsif params[:user][:password].nil? render :status => 400, :json => {:message => 'User request must contain the user password.'} return end if params[:user][:email] duplicate_user = User.find_by_email(params[:email]) unless duplicate_user.nil? render :status => 409, :json => {:message => 'Duplicate email. A user already exists with that email address.'} return end end render :status => 400, :json => {:message => resource.errors.full_messages} end end protected # If you have extra params to permit, append them to the sanitizer. def configure_sign_up_params devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute, :first_name, :last_name, :access_code]) end end 

I am sure that my main problem at the moment is the format of my parameters, so any push in the right direction for this would be wonderful. I found this post , but it's hard for me to understand what got their API to work ...

+5
source share
3 answers

Here are 2 solutions, choose the one you like.

  • Override devise_parameter_sanitizer:

     class ApplicationController < ActionController::Base protected def devise_parameter_sanitizer if resource_class == User User::ParameterSanitizer.new(User, :user, params) else super # Use the default one end end end 
  • Override sign_up_params:

     def sign_up_params params.require(:user).permit(:email, :password, :password_confirmation) end 

Why?

If you delve into the Devize ParameterSanitizer , the resource name will be :api_v1_user , not just :user because of your routes:

 namespace :api do namespace :v1 do devise_for :users, controllers: { registrations: 'api/v1/registrations' } end end 

The error resource_name causes sign_up_params always returns an empty hash {}

+2
source

Why not use a simple_token_authentication gem?

Extremely easy to set up:

 # Gemfile gem "simple_token_authentication" bundle install rails g migration AddTokenToUsers "authentication_token:string{30}:uniq" rails db:migrate # app/models/user.rb class User < ApplicationRecord acts_as_token_authenticatable # [...] end 

In your routes:

 # config/routes.rb Rails.application.routes.draw do # [...] namespace :api, defaults: { format: :json } do namespace :v1 do resources :classrooms resources :notifications end end end 

In your controllers:

 # app/controllers/api/v1/classrooms_controller.rb class Api::V1::ClassroomsController < Api::V1::BaseController acts_as_token_authentication_handler_for User # [...] end 

Example call using the RestClient gem:

 url = "http://localhost:3000/api/v1/classrooms/" params = {user_email: ' john@doe.com ', user_token: '5yx-APbH2cmb11p69UiV'} request = RestClient.get url, :params => params 

For existing users who do not have a token:

 user = User.find_by_email(" john@doe.com ") user.save user.reload.authentication_token 
0
source

Why don't you try something like this:

 user = User.create(sign_up_params) if user.save render status: 200, json: @controller_blablabla.to_json else render :status => 400, :json => {:message => @user.errors.full_messages} end 

or even better. You can use something like a tiddle gem to make the session more secure:

 respond_to :json def create user = User.create(sign_up_params) if user.save token = Tiddle.create_and_return_token(user, request) render json: user.as_json(authentication_token: token, email: user.email), status: :created return else warden.custom_failure! render json: user.errors, status: :unprocessable_entity end end 

You can use httpie --form to make a request:

 http --form POST :3000/users/sign_up Accept:'application/vnd.sign_up.v1+json' user[email]=' he@llo.com ' user[username]='hello' user[password]='123456789' user[password_confirmation]='123456789' 

Do not forget:

 def sign_up_params params.require(:user).permit(:username, :email, :password, :password_confirmation) end 

I don’t know what I missed, let me know if I am wrong or something is wrong and I didn’t understand!

Hello!

0
source

Source: https://habr.com/ru/post/1264550/


All Articles