12/08/2018, 15:17

Handling exception gem Cancancan Rails

Chào các bạn, việc phân quyền người dùng khi bạn tạo ra một ứng dụng là việc quan trọng và không thể thiếu. Với Rails việc này trở nên dễ dàng khi bạn sử dụng gem "Cancancan" để xử lý. Sử dụng là một chuyện nhưng để handle được những exception mà nó sinh ra lại không phải dễ dàng. Trong bài viết ...

Chào các bạn, việc phân quyền người dùng khi bạn tạo ra một ứng dụng là việc quan trọng và không thể thiếu. Với Rails việc này trở nên dễ dàng khi bạn sử dụng gem "Cancancan" để xử lý. Sử dụng là một chuyện nhưng để handle được những exception mà nó sinh ra lại không phải dễ dàng. Trong bài viết này mình sẽ đưa ra một số cách để handle exception của gem Cancancan, sau đây mình sẽ đi và chi tiết.

  • Ngoại lệ CanCan::AccessDenied sẽ được raise ra khi gọi method authorize! trong controller action (hoặc sử dụng load_and_authorize_resource cho tất cả các controller action) mà User không được phép thực hiện action đã cho. Một thông điệp sẽ sinh ra:

Cách 1: Xử lý trực tiếp trong action

authorize! :read, Article, message: "Unable to read this article." Hoặc: raise CanCan::AccessDenied.new("Not authorized!", :read, Article)

Bạn có thể định nghĩa trong file config/locales/en.yml để custom thông điệp này:

en:
  unauthorized:
    manage:
      all: "Not authorized to %{action} %{subject}."
      user: "Not allowed to manage other user accounts."
    update:
      project: "Not allowed to update this project."

Trong đó: action bao gồm: read, manage, create, update,... subject: all, object,...

Cách 2: Bắt ngoại lệ và sửa đổi hành vi của nó trong ApplicationController

  • Hiển thị ra 1 thông báo và chuyển về Home page:
class ApplicationController < ActionController::Base
  rescue_from CanCan::AccessDenied do |exception|
    respond_to do |format|
      format.json { head :forbidden }
      format.html { redirect_to main_app.root_url, alert: exception.message }
    end
  end
end
  • Hoặc bạn có thể tạo ra file public/403.html và render khi có ngoại lệ:
class ApplicationController < ActionController::Base
  rescue_from CanCan::AccessDenied do |exception|
    render file: "#{Rails.root}/public/403.html", status: 403, layout: false
  end
end

Cách 3: Custom lại trang mà bạn muốn chuyển tới cho từng User

Ở đây mình đưa ra cách giải quyết mà mình đã từng làm để chuyển về trang theo từng loại User đã được phân quyền khi có ngoại lệ. Giả sử mình có: Admin - quản trị, User - người dùng thông thường của ứng dụng

  • Với quyền là Admin, khi gặp exception mình sẽ chuyển về root của admin (admin_root_url)
  • Với quyền là User, khi gặp exception mình sẽ huyển về root của user (root_url)

Mình xử lý như sau:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  rescue_from Exception do |exception|
    flash[:warning] = exception.message
    redirect_to_root
  end

  rescue_from ActiveRecord::RecordNotFound do |exception|
    flash[:warning] = exception.message
    redirect_to root_url
  end

  private

  def redirect_to_root
    (current_admin_user && namespace == "admin") ?
      redirect_to(admin_root_url) : redirect_to(root_url)
  end
 end

Bạn hãy custom lại và handling exception theo cách mà bạn muốn ^_^

Trong bài viết này mình đã đưa ra 1 số cách handing exception khi sử dụng gem Cancancan để phân quyền cho người dùng. Bạn hãy lựa chọn cho ứng dụng của mình 1 cách hợp lý hay có thể đưa ra cách giải quyết tốt hơn. Rất mong nhận được sự dóng góp của các bạn!! Good luck! Link tài liệu tham khảo: https://github.com/CanCanCommunity/cancancan/wiki/exception-handling

0