2016-08-24 3 views
2

Я получаю следующее сообщение об ошибке при попытке получить доступ к журналу в методе моего sessions контроллера:Почему current_user вызывается для рендера в контроллере?

JWT::DecodeError (Nil JSON web token): 

lib/json_web_token.rb:11:in `decode' 
app/helpers/sessions_helper.rb:15:in `current_user' 
app/controllers/api/sessions_controller.rb:11:in `create' 

Если я закомментировать моей render json: user в моем ответе контроллера, все хорошо, за исключением того, мне нужно ответить с пользователь ... Почему на самом деле это метод current_user, вызываемый по линии 11 sessions_controller.rb. Вот соответствующий код:

Библиотека/json_web_token.rb

require 'jwt' 

class JsonWebToken 
    def self.encode(payload, expiration = 24.hours.from_now) 
    payload = payload.dup 
    payload['exp'] = expiration.to_i 
    JWT.encode(payload, Rails.application.secrets.json_web_token_secret) 
    end 

    def self.decode(token) 
    JWT.decode(token, Rails.application.secrets.json_web_token_secret).first 
    end 
end 

sessions_helper.rb

require 'json_web_token' 

module SessionsHelper 
    def create_session(user) 
    session[:user_id] = user.id 
    end 

    def current_user 
    auth_token = request.headers["Authorization"] 
    if auth_token 
     auth_token = auth_token.split(" ").last 
     begin 
     decoded_token = JsonWebToken.decode auth_token 
     rescue JWT::ExpiredSignature 
     return 
     end 
     @current_user ||= User.find_by(auth_token: auth_token) 
    end 
    end 

    def log_out(user) 
    logged_in? ? user.generate_authentication_token! : user.destroy_token! 
    auth_token = user.auth_token 
    user.update_attribute(:auth_token, auth_token) 
    end 

    def logged_in? 
    current_user.present? 
    end 

    def authenticate_with_token! 
    render json: { errors: "Not authenticated" }, status: :unauthorized unless logged_in? 
    end 

    def log_in(user) 
    create_session(user) 
    user.generate_authentication_token! 
    user.update_attribute(:auth_token, user.auth_token) 
    end 

    def authenticate_as_self_or_admin! 
    render json: { errors: "Not authorized" }, status: :unauthorized unless is_self? || is_admin? 
    end 

    def is_self? 
    user = User.find(params[:id]) 
    auth_token = request.headers["Authorization"] 
    auth_token = auth_token.split(" ").last if auth_token 
    user.auth_token != auth_token 
    end 

    def is_admin? 
    if logged_in? && current_user.authenticate(params[:password]) 
     current_user.admin 
    end 
    end 
end 

sessions_controller.rb

class Api::SessionsController < ApplicationController 
    before_action :authenticate_with_token!, only: [:destroy] 
    def new 
    end 

    def create 
    user = User.find_by(email: params[:session][:email].downcase) 

    if user && user.authenticate(params[:session][:password]) 
     log_in user 
     render json: user, status: :created 
    else 
     render json: user, status: :unprocessable_entity 
    end 
    end 

    def destroy 
    log_out current_user 
    render status: 204 
    end 
end 

user.rb

require 'json_web_token' 

class User < ApplicationRecord 
    attr_reader :current_password 

    before_save { email.downcase! } 
    before_create :generate_authentication_token! 
    before_update :reset_confirmed!, :if => :email_changed? 
    has_secure_password 
    has_many :posts 
    has_many :comments 
    has_many :votes 
    VALID_EMAIL_REGEX = /\A[\w+\-.][email protected][a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i 
    validates :email, presence: true, length: { maximum: 255 }, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false } 
    validates :username, presence: true, length: { maximum: 24 }, uniqueness: { case_sensitive: false } 
    validates :password, presence: true, length: { minimum: 8 } 
    validates :auth_token, uniqueness: true 

    def generate_authentication_token! 
    begin 
     self.auth_token = JsonWebToken.encode('id' => self.id, 'username' => self.username, 'email' => self.email, 'bio' => self.bio, 'confirmed' => self.confirmed, 'admin' => self.admin, 'points' => self.points) 
    end while self.class.exists?(auth_token: auth_token) 
    end 

    def destroy_token! 
    self.auth_token = nil 
    end 

    def reset_confirmed! 
    self.confirmed = false 
    end 

    def upvotes 
    self.votes.where(polarity: 1) 
    end 

    def downvotes 
    self.votes.where(polarity: -1) 
    end 

    def update_with_password(user_params) 
    current_password = user_params.delete(:current_password) 
    user_params[:password] = current_password if user_params[:password].nil? 

    if self.authenticate(current_password) 
     self.update(user_params) 
    else 
     self.errors.add(:current_password, current_password.blank? ? :blank : :invalid) 
     false 
    end 
    end 
end 

Нет, я не использую изобрести. Я действительно надеюсь, что мои глаза просто устали здесь ...

+1

Где определяется 'Rails.application.secrets.json_web_token_secret'? – Ven

+0

Этот секрет определен в 'local_env.yml', который скрыт git игнорируется. В консоли rails, если я пытаюсь получить доступ к переменной через 'Rails.application.secrets', она работает нормально. –

+1

@LouisCruz, можете ли вы разместить код в своей модели 'user.rb'? –

ответ

2

Оказывается, на самом деле вызывается current_user, так как это имя объекта по умолчанию для активных сериализаторов. Я изменил имя своего метода current_user, чтобы избежать этого конфликта. Here are the relevant docs.

Смежные вопросы