如何用ApiConstraints调解Devise reset-password路由?

时间:2017-07-06 16:04:33

标签: ruby-on-rails ruby devise http-headers api-design

我正在使用devise_token_auth,一切正常,直到我向路线添加API约束:constraints: ApiConstraint.new(version: 4, default: true)

Rails.application.routes.draw do
  namespace :api do
    scope module: :v4, constraints: ApiConstraint.new(version: 4, default: true) do
      # Token auth routes available at /api/auth
      mount_devise_token_auth_for "User", at: "auth"
    end
  end
end

添加这些约束会限制对路由的访问,除非请求包含正确的标头:

class ApiConstraint
  attr_reader :version

  VENDOR_MIME = "application/vnd.myproject-v%d"

  def initialize(version: "4", default: false)
    @version, @default = version, default
  end

  def matches?(request)
    byebug # <-- I wish there was something like request.current_path available
    return @default unless request.headers.key?("accept")
    request
      .headers
      .fetch("accept")
      .include?(VENDOR_MIME % version)
  end
end

我意识到这对于我们通过电子邮件获得的重置密码链接存在问题:

https://myproject.herokuapp.com/api/auth/password/edit?reset_password_token=...

...因为它无法携带任何标题!

我可以将用户重定向到一个网页,然后使用相应的标题进行AJAX调用,但我想知道是否有办法增强我的routes.rbApiConstraint类来进行异常处理在/auth/password/edit路线?

1 个答案:

答案 0 :(得分:1)

您可以使用request.urlrequest.fullpathrequest.params来访问所需的数据。

更重要的是,为了弄清楚在运行时哪些方法可用,一旦REPL在您放置byebug调试器条目的行上打开,您可以使用以下方法(假设您使用pry):

ls # display everything in the current scope
cd request # or any other variable or instance variable.
cd .. # you can navigate your code as if it was a filesystem

request.methods.grep /path/
request.methods.grep /url/
request.methods.grep /param/

# or

cd request
methods.grep /query/

OP更新

# api_constraint.rb
def initialize(version: "4", default: false, exceptions: [])
  @version, @default, @exceptions = version, default, exceptions
end

def matches?(request)
  return true if @exceptions.include? request.path
  ...
end
#routes.rb
scope module: :v4, constraints: ApiConstraint.new(version: 4, default: true, exceptions: [
  "/api/auth/password/edit"
]) do
  ...
end