권한 부여 접근 모델의 특정 필드

11122 단어 cancan

묘사

Cancan은 내가 가장 좋아하는 Rails 권한 수여 플러그인이지만 세부 사항을 깊이 파고들 때 어려움을 발견한 것 같다.주어진 모델의 특정 필드에 대해 우리는 어떻게 역할 기반 권한을 얻습니까?
예를 들어, 영업 및 고객 서비스 담당자가 사용자의 주소 필드를 편집할 수 있지만 관리자 또는 영업 담당자만 사용자의 고객 번호를 업데이트할 수 있다고 가정합니다.cancan으로 사용자 자원을 불러오는 것은 문제없지만, 보기에서 필드 기반 권한 논리는 곧 엉망이 될 것입니다.
# e.g., app/views/users/_form.html.erb

<% if current_user.role?(:admin, :sales) %>
  <%= f.text_field :customer_number %>
<% else %>
  <%= @user.customer_number %>
<% end %>

<% if current_user.role?(:sales, :csr) %>
  <%# edit address fields %>
<% else %>
  <%# display address %>
<% end %>
이것은 마치 내가 사람들 (나 자신을 포함) 이 겪는 매우 흔한 문제를 본 것 같지만, 나는 그것을 어떻게 최선의 방법으로 해결해야 할지 시종 확실하지 않다.가능하다면, 나는 이 화제에 대해 토론을 전개하고 싶다.
주:캔캔의 범위 내에 있지 않으면 이 문제를 끝내는 것을 완전히 이해합니다.

토론 #1

나도 이 기능에 관심이 있어.

토론 #2

저도요.

토론 #셋

한 가지 해결 방안은 사용자 정의 조작을 사용하는 것입니다. 자세한 정보는 this wiki page을 참조하십시오.
또 다른 해결 방안은 trusted-params 플러그인을 사용하지만, Rails 3과 호환되지 않는다.내부 Rails 방법과 모든 해시를 추하게 재구성했다. 이것은 내가 CanCan에 내장하고 싶은 것이 아니다.
둘 다 이상적이지 않고 CanCan 처리 권한에 부합하지 않는다는 데 동의합니다.CanCan을 통해 이 점을 더 잘 실현할 수 있다는 것에 대해 다른 생각은 없으신가요?

토론 #4

네, Active Record를 다시 쓰는 방법이 가장 좋은 방법은 아니에요.
현재 나는 이런 해결 방안을 사용하고 있다.
컨트롤러:
def update
  @user = User.find( params[:id] )

  attrs = params[:user]
  authorize? :update, @user, attrs

  @user.update_attributes(attrs)

 ...
기능:
can :update, User do | subject, params |
  ! user.toucheble_parameters(subject).each { |p|
    break if params.exists? p
  }.nil?
end
여기서 User#toucheble parameters는 사용자가 만질 수 있는 테마 매개 변수 목록입니다.
어쩌면 캔/can 같은 방법만 더 좋을지도 몰라요?그런데 행동이 없어요?
예:
can_touch_attributes User, [:name, :email], :user_id=>user.id  # Anybody can touch his name and email

can_touch_attributes User, [:is_admin], :role => 'admin'  # Only admin can touch is_admin

...

can_touch_attributes? @user, attrs
나는 우리가 속성을 검사하는 조작을 필요로 하지 않는다고 생각한다.그러나 누군가가 그것을 필요로 한다면, 그는 첫 번째 해결 방안을 사용할 수 있다.

토론 #5

다피,
이곳의 평론은 매우 좋다.나는 네가 Ability.rb에서 사용하는 기교를 좋아한다.
나는 아직도 이런 상황을 생각하고 있다.
<%= @product.price if current_user.role?(:admin, :sales :distributor) %>
<%= @product.cost if current_user.role?(:admin, :sales) %>
이 예들 중에서, 나는 누가 :read 어떤 속성을 제어할 수 있는지 제어해야 한다.이것은 악화될 것이다.편집 제품 양식을 봅니다.
<% form_for @product do |f| %>
  ...
  <% if current_user.role?(:admin) %>
    <%= f.text_field :price %>
    <%= f.text_field :cost %>
  <% elsif current_user.role?(:sales) %>
    <%= @product.price %>
    <%= @product.cost %>
  <%= elsif current_user.role?(:customer_service) %>
    <%= @product.price %>
  <% end %>
  ...
<% end %>
나는 네가 can_touch_attributes宏에 대해 이미 알고 있다고 생각하지만, 나는 몇 가지 예를 생각해 낼 수 있다. 그 중에서 나는 동작/속성 조합을 바탕으로 권한을 얻기를 바란다.속성뿐만 아니라

토론 #6

다피,
나는 cancan Custom Actions와 네가 위에서 묘사한 기술을 잘 결합시키고 싶다...
매사에 능력을 기준으로 삼다.rb는 나에게 매우 매력적이다.이 문제를 계속 탐구해서 몇 가지 방법을 생각해 낼 수 있는지 봅시다.

토론 #7

can 만약 :banned 추가 매개 변수, 즉 속성을 나타내는 기호를 지원한다면 어떻게 해야 합니까?이것도 일련의 기호일 수 있다.
can :manage, Article, :content, :user_id => user.id

And similar for can?.

can? :update, @article, :content

In both cases the last symbol is optional, and if not present it will represent all attributes which is the current behavior. The check for each attribute would happen automatically in authorize_resource in the controller.

This conflicts a little with the existing API but let's not worry about that when brainstorming.

토론 #8

Yes. Something like this.

소견

To check parameters that are not permitted to update. Don't show it in the form.

<% if can? :update, @user, [:is_admin, :roles] %>
  <%= form.input :is_admin %>
  <%= form.input :roles %>
또는
<% if can? :update, @article, :banned  %>
  <%= form.input :banned %>

능력


관리자는 모든 속성을 업데이트할 수 있습니다.
can :update, Article, user.is_admin => true

# is similar to

can :update, Article, :attributes => :all, user.is_admin=>true
소유자는 Article를 제외한 모든 속성을 업데이트할 수 있습니다.
can :update, Article, :exclude => [ :banned ], :user_id=>user.id 
또는
can :update, Article, :attributes => [ :subject, :content, :published ], :user_id=>user.id
아니면 그냥
can :update, Article, [ :subject, :content, :published ], :user_id=>user.id

컨트롤러


사용자가 이 능력이 없거나 비활성화 속성을 업데이트하려고 시도하면 이상이 발생합니다.
authorize! :update, @article, params[:user]

# or

authorize! :update, @article, params[:user].keys
사용자가 성명된 업데이트

토론 #9

능력이 없으면 이상을 일으킬 수 있습니다.
authorize! :update, Article
두뇌 폭풍의 충격: 만약 그가 능력이 있다면 금지된 속성을 몰래 삭제한다.:exclude 아마도 cannot 옵션은 @article으로 처리할 수 있을 것이다.
#  params[:user] = { :content=>'test', :banned=>false }

sanitize :update, @article, params[:user]

# now params[:user] = { :content=>'test' }
불가능할 것 같지만 완전히 소홀히 해서는 안 된다.

컨트롤러


우선 코드에 작은 오류가 있습니다.권한params[:user]을 부여하고 있지만 사용 중authorize! :update, @article, params[:article]입니다.
나는 우리가 반드시 사용해야 한다고 생각한다params[:user].keys.나는 이것이 우리가 파라메스 산열 키를 사용하려고 한다고 가정하기 때문에 매번 호출할 때마다 sanitize 좀 멍청하다고 생각한다.또 초보자들을 곤혹스럽게 할 것이라고 생각한다.이렇게 하는 것은 매우 쉽다.
can :update, Article
cannot :update, Article, :banned

Also silently removing attributes with sanitize might cause some confusion. I find that to be the case with the current behavior of attr_accessible. Better to raise an authorization error and let the developer rescue from that early if he wants.

Everything else looks good though. I'll definitely consider this in a major update to CanCan.

토론 #10

dapi, this looks great. A couple comments.

능력

You use the hash key :exclude. The Rails convention here seems to be the key :except. I think we should stick with that.

If we use with :attributes => :all or :attributes => [...], We might not need an API change. We could simply treat :attributes and :except as reserved keys. This might not be entirely favorable, though, as someone might have an attributes field on one of their models.

# user can only see blue products
can :read, Product, :attributes=>"blue"
너의

토론 #11

방법을 계속해라.나 이거 좋아해.나는 최근에 줄곧 Searchlogic를 고치고 있는데, 폼 파라미터를 정리하는 것은 아마도 매우 지루할 것이다.나는 위생 처리를 한쪽에 두지 말고 사후에 다시 생각하지 말라는 생각을 좋아한다.:except리안,
아, 내 이전의 평론은 아마도 너와 같은 시간에 쓴 것일 거야.내가 글을 올린 후에야 나는 비로소 너의 평론을 보았다.cannot 처리:attributes => :all로 목적을 달성할 수 있을 것 같다.이것은 실제로 보기에 매우 우아하다.만약 속성 목록이 항상 하나의 수조라면, sanitize 의 필요를 뛰어넘을 수도 있습니다.
다피, 더 명확하게 말하자면, 나는 이것이 라이언이 원하는 것이라고 생각한다.
def check_attributes(attributes)
  if attributes.is_a? Hash
    attributes = attributes.keys
  end
  ...
end
이것은 또 다른 생각을 가져왔다.만약 속성 그룹이 관련되거나 끼워 넣은 속성을 포함한다면 어떻게 합니까?너는 이 일을 좋아하니?
can :update, Article                        # all attributes
cannot :update, Article, [:banned]          # except for :banned

can :update, Project, [:priority, :status]  # only :priority and :status
나도 예외를 제시하는 것이 위약 행위에 이롭다는 것에 동의한다.필요하면 로고를

토론 #12

에 전달하여 '강제' 로 파라미터를 제거할 수 있습니까?notes_attributes@macek, 덧붙인 속성 부분이 작용합니다. 왜냐하면 이것은 모델의 속성으로 여겨지기 때문입니다.그러나 특정한 깊이 박힌 속성에 대한 접근을 제어하려면 문제가 될 것입니다.이런 상황은 컨트롤러 밖에서 발생하기 때문에 Notesanitize 모델에서 검사를 해야 한다는 것을 알 수 없다.
실제로 중첩 속성도 CanCan의 현재 행동에 대한 문제이지만 불평을 듣지 못했다.나는 그들이 단지 선행 필터로 이 문제를 해결할 뿐이라고 추측한다.

토론 #13

에 관해서 나는 용례를 보기 어렵지만, 이것은 용례가 없다는 것을 의미하지는 않는다.나는 이 문제를 더욱 토론할 것이지만, 우리가 이 점을 더 많이 본 후에 다른 문제에서 토론할 수도 있다.can?는 단지 두뇌 폭풍의 생각일 뿐이다.보기의 모든 필드에 대한 검사 current_ability 는 매우 번거로울 것입니다.사용자 권한에 따라 필드를 자동으로 숨기거나 표시할 수 있는 단독 폼 생성기gem가 있을 수도 있습니다.이 또한 Formtastic과 통합하여 더욱 편리하게 할 수 있다.

토론 #14

리안,
사용자가 비밀 필드를 업데이트하려고 할 때 권한 부여 오류를 제기하는 것이 가장 좋다는 의견에 동의합니다.
Formtastic 정보이것은 좋은 생각이다.
우리는 sanitize를 사용하여 필드를 자동으로 삭제하고 명확한 폼을 얻을 수 있습니까?Formtastic을 변경할 필요가 없습니다.
# associations
can update, Project, [:categories, :members]

# nested attributes
can :update, Project, [:notes_attributes]
또는
def new
  authorize! :create, User
  @user = User.new
  sanitize :create, @user # Removes secret fields
end

...

= semantic_form_for @user do |form|
  = form.inputs      # Shows existent fields only
이 경우sanitize 동작이 자동으로 감지됩니다.

토론 #15

다피,
대부분의 사람들이 <%= f.inputs %> 매크로를 한 번에 모든 필드를 저장하지 않을 것이라고 나는 확신한다.수동으로 폼을 만드는 능력은 매우 중요하다.

토론 #16

@ryanb는 이미 알고 있지만 rails3(activerecord)에는 대규모 분배 보안 모듈이 있습니다.
http://github.com/rails/rails/blob/master/activemodel/lib/active_model/mass_assignment_security.rb
cancan은 이 점을 이용해야 한다. 나는 신뢰받는 params를 개조하여 이 점을 이용할 수 있다고 생각한다.

토론 #17

@rbritom, 와, 너무 좋아, 난 몰라.조사할 때가 됐어. 아마도 나는 철도 기사에 관한 프로그램을 할 수 있을 거야.

토론 #18

@ryanb=D
activerecord의 일부분을 말하지만, 실제로는 active 모델의 일부분이기 때문에 DB 백업이 없는 클래스에 적용할 수 있습니다.

토론 #19

CanCan에서 유사한 sanitize_for_mass_assignment를 얻게 되어 기쁩니다:

토론 #20

저는 곧 새로운 2.0지점에서 이 점을 추진할 것입니다.191기를 참고하여 2.0계획의 서로 다른 변화를 이해하고 거기서 피드백을 제공해 주십시오.

토론 #21

너무 좋아요.나는 이것에 대해 매우 흥분했다.

토론 #22

토론 #23

끝났다. 왜냐하면 이것은 현재의 2.0 branch 이기 때문이다.그것은 아직 완전히 광택을 내고 일을 하지 않았을 수도 있지만, 기능은 바로 거기에 있다.어이, 이게 어떻게 된 일이야?그것은 버림받은 것 같은데, 새로운 것이 있습니까?

토론 #24

@s 전체 CanCan

토론 #25

참조 새 PR:https://github.com/CanCanCommunity/cancancan/pull/474

좋은 웹페이지 즐겨찾기