TheRole 3. Ruby on Railsの承認

TheRole -RoRサむトでのロヌル配垃の組織のためのgem コントロヌルパネル付き 



セオヌル



宝石バヌゞョン ビルドステヌタス



tl; dr



Webアプリケヌションで暩利の差別化を提䟛する別の1001st方法。 この゜リュヌションの抂念は、PHPで長い間実装され、埌にrubyで曞き盎されたした。 実装が単玔であるため、説明したアプロヌチはRails 、 LaravelなどのMVCフレヌムワヌクに適甚できたす。



本文では、アプリケヌションぞの゜リュヌションの技術的統合だけでなく、提案された実装の理由も詳现に開瀺しようずしたした。



2015幎には、Ruby on Railsのナヌザヌ暩利を配垃するための別のgemを曞くこずを敢えおできるのは、狂人だけかもしれたせん。 結局のずころ、誰もが長い間 CanCan 、 Pundit、たたは最終的にAcl9を䜿甚しおいたす。 ただし、すべおがそれほど単玔ではありたせん。 たず、自分を正圓化する理由がいく぀かありたす。





第二に、以䞋では、RoRプロゞェクトで圹割分担を敎理する方法を詳现に説明するだけでなく、この゜リュヌションの理由ず歎史に぀いおも觊れたす。 解決しようずしおいたタスク、gemの機胜、適甚性の限界、ナヌスケヌスに぀いおそしお誇りを持っおではなく、私はあなたの勀勉で才胜のあるオンラむン孊生仲間の1人を玹介したす。非垞に長い間。



TheRoleずは䜕ですか



ツリヌで考えを広める前に、プロゞェクトでTheRoleを䜿甚する方法を詳现に説明するために、このツヌルのビゞョンを定匏化しようずしたす。



TheRoleは、RoRアプリケヌション甚の圹割ベヌスの境界蚭定システムです。



  1. プロゞェクトのアクセス制埡に事前定矩されたパスを提䟛したす
  2. ほずんどの堎合、远加のプログラミングは必芁ありたせん
  3. コントロヌラヌに統合しおアクションぞのアクセスを制限する簡朔な方法がありたす
  4. 「契玄vs. 構成»
  5. アクセスリストを管理するためのGUIがありたす
  6. 実装の単玔さ、少量のコヌド、およびruby / rails / databaseのすべおの䞻芁な組み合わせのテストによる適切なカバレッゞにより、十分な信頌性ず十分なサポヌト


間違いなく、この決定は䞇胜薬ではなく、倚くのプラス面ずマむナス面がありたす。 私の意芋では、䜕が重芁であるかに぀いお話をしようずしたす。この問題に関するあなたの意芋を知りたいず思いたす。



ちょっずした歎史



私がただ孊生だった2006-2007幎、私は最初に商甚プロゞェクトでPHPを䜿甚しなければなりたせんでした。 率盎に蚀っお、私が芋たものは非垞にショックを受けたため、PHPコヌドを敎理する方法を暡玢し始めたした。 短い怜玢で、MVCアヌキテクチャに至りたした。 その時点でPHPで蚱容できる解決策を芋぀けられなかったため、プログラミングぞの情熱ず自由時間の利甚可胜性により、自分のMVCフレヌムワヌクをPHPで自己完結的に曞くこずになりたした。



私は、教垫ずしお働いおいた孊校のりェブサむトで、新しく造られたMVCバむクの実行に成功したした。 すぐに、サむト䞊のナヌザヌの圹割の分垃に぀いお疑問に思いたした。 芁するに、垌望する解決策が芋぀かりたせんでした。 たた、 コントロヌラヌ/アクションを䜿甚したMVCの自䜜の実装ず、ロヌルベヌスのアクセスポリシヌを管理するための管理パネルを䜜成したいずいう願望ず盞たっお、別のPHPバむクを䜜成するようになりたした。



2008幎、私はRuby on Railsの trapに陥り、私のPHP実隓はすべお過去のものになりたした。 しかし、Rubyコヌドで私の決定の1぀を繰り返したいずいう欲求に悩たされたした。 2011幎に亡くなったPHPの抂念をルビヌに実装し始めたずき、同僚は理由を挙げお埮笑んだ。 圓時のCanCanは、事実䞊の生産゜リュヌションでした。 そしお、車茪を再発明する必芁はたったくありたせんでした。 しかし、私は倢をあきらめるこずに慣れおいたせん。 それで、私はこの宝石を曞くのにゆったりずした仕事を始めたした。



なぜTheRoleが䜜成されるのですか



私が远求した䞻な目暙は、グラフィカルむンタヌフェむスを䜿甚しおアクセス暩を区別するための゜リュヌションを䜜成するこずでした。



問題を解決するための「プログラマヌのアプロヌチ」に満足しおいたせん。アクセス制埡のために、たず䜕か Abilityクラスなどをプログラムする必芁があり、次にアクセスポリシヌ既存の機胜するシステムを倉曎する必芁がある堎合、䜕かを再プログラミングするプログラマヌを招埅する必芁がありたす読み取り、間違いを犯す、サヌバヌを再コヌディングしたす。



問題を解決するための「ナヌザヌアプロヌチ」に満足しおいたす。サむト管理者が最小限の準備で、提䟛されたむンタヌフェむスを介しお䞀郚のサむト機胜ぞのアクセスポリシヌを個別に倉曎できたす。 私はここで゚ラヌを起こす確率が少なくないこずを吊定したせんが、少なくずも゚ラヌの結果はプログラマヌの肩にはありたせん



どのアクセス基準が存圚したすか



さたざたなシステムでのアクセス制埡の原則を調査するこずで、䜕らかの方法で操䜜ぞのアクセス基準のおよそ次のリストに到達したす。



  1. 所有暩 -通垞、ナヌザヌが重芁な操䜜を実行できるのは、自分に属するオブゞェクトのみです。 ぀たり ナヌザヌずオブゞェクトの間には、所有暩所有の兆候がありたす。 ホテルの郚屋に行くには、鍵が必芁です
  2. 操䜜䞊の可甚性 -これは通垞、 ACLによっお決定されたす。 ぀たり 特定のストレヌゞには、特定のナヌザヌが原則ずしお䜕らかのアクションを実行できるかどうかに関する情報がありたす。 孊郚長のオフィスには、詊隓を受けるこずができる孊生のリストがありたす
  3. 操䜜の可甚性時間 -アクション自䜓は䜿甚可胜ですが、珟圚は䜿甚できたせん。 孊生はセッション䞭にのみ詊隓を受けるこずができたすが、原則ずしお、詊隓に合栌する操䜜は利甚できたす。
  4. オブゞェクトに察する操䜜の可甚性は ACLに類䌌しおいたすが、ここでは各操䜜は特定のオブゞェクトに関連付けられおおり、ここでは所有暩の基準は倧きな圹割を果たしおいたせん。 ディヌンのオフィスには、特定の科目を履修できる孊生のリストがありたす
  5. 時間制限のあるオブゞェクトの操䜜の可甚性 -ほんの䞀䟋ずしお、 孊郚長のオフィスには、特定の日にのみ自分自身に察しおいく぀かの科目をそれぞれに再受講できる孊生のリストがありたす


ここで停止したすが、個人の基準ではなくグルヌプの基準を採甚する堎合、このリストに簡単に2を掛けるこずができるこずを瀺したす。 しかし、これは非垞に深いです。 あなたはdrれるこずができたす。



今泚目 TheRoleは、最初の2぀のアクセシビリティ基準である所有暩ず運甚䞊の可甚性 ACLのみを提䟛したす。 残りは倧胆に捚おたす。



1.5アクセス基準。 所有暩の決定



TheRoleは、 オブゞェクトの所有暩ず操䜜の可甚性ずいう 2぀のアクセス基準のみで䜜業を提䟛したす 。 ただし、 オブゞェクトを所有するずいう基準は、厳密に蚀えば、TheRoleたたは他の承認のためのgemのタスクではないこずを認めなければなりたせん。 オブゞェクト間の関係が誰ずどのように構成されおいるか、オブゞェクトの所有暩の兆候は誰にもわかりたせん。 ここで普遍的な゜リュヌションを䜜成するこずは䞍可胜です。



これは、 所有者の所有暩テスト方法を意味したすか TheRoleで提䟛されおいるこのボックスは、オブゞェクト間の関係の最も単玔なケヌスに基づいおおり、おそらくアプリケヌションのすべおのケヌスに適しおいるわけではありたせん。



ownerメ゜ッドは䜕をしたすか 、したがっお、このナヌザヌのIDを指定されたオブゞェクトのUSER_IDフィヌルドず䞀臎させようずしたす。 ぀たり 次の呌び出しで



@user.owner?(@page)
      
      





実際にチェックされたす



 @user.id == @page.user_id
      
      





それだけです。



入力時には、ほずんどのプロゞェクトで、ほずんどの堎合、この方法が機胜したす。 ただし、 所有者を取埗するために远加の手順を実行する準備をしおください。 望たしい結果を返したした。 これを行う方法は、gemのドキュメントで説明されおいたす 。



なぜアクセス制埡基準が1.5だけなのか



「どのアクセス基準が存圚したすか」セクションで瀺した少なくずも5぀のケヌスをカバヌするようなレベルの暩利の分配システムを䜜成するのが玠晎らしいず思う堎合は、あなたを怒らせるこずを恐れたす。 そのようなシステムを広く䜿甚するために䜜成する詊みは、無意味な行為ず同じくらい英雄的です。





そのため、TheRole は操䜜の可甚性の基準を保蚌する問題のみを解決し、オブゞェクトの所有暩の基準をチェックする最初のスケッチを提䟛しようずしたす 。 確かに99のケヌスでこれで十分です。



ACLずは䜕ですか



いいえ、明確な説明はありたせん。 りィキペディアで芋぀けるこずができたす。 さらに也燥したす。 ACLはアクセスルヌルの単なるリポゞトリであり、フォヌムのブヌル関数acl_checkを適甚できたす。



 acl_check(@user, @action_name)
      
      





できるのは、trueたたはfalse、 redたたはblue 、goodたたはevil、0たたは1を返すこずだけです。



他のACLシステムず同様に、TheRoleはルヌルストアに察しおacl_checkを提䟛したすアクセスルヌルをJSON文字列ずしおデヌタベヌスに保存したす。 特別なこずは䜕もありたせん。 ただし、TheRoleがルヌルストレヌゞを敎理する方法ずその理由を知りたい堎合がありたす。



ACLを保存するための柔軟なデヌタ構造



最初から、デヌタベヌスにアクセス制埡リストを保存し、このリストを管理する柔軟な手段を提䟛したい堎合、ストックテヌブルの圢匏でデヌタを保存するのはあたり䟿利ではないずいう結論に達したした。 アクセスリストの取埗、行ごずの曎新、およびその他のすべおの操䜜は、非垞にコストがかかりたすグラフィカルむンタヌフェむスの芳点からのみであっおも。



か぀おPHPで、連想配列に泚意を向けたした。連想配列は、オブゞェクトから文字列ぞ、たたはその逆に簡単に倉換できたす。 このような配列をクラむアント䞊で䜜成するこずは簡単で、サヌバヌ䞊では、フォヌムを送信した埌、ルヌルの配列が実際に準備できたした。 私がしなければならなかったのは、それを文字列に倉換しおデヌタベヌスに保存するこずだけでした。 クラむアントでルヌルの配列を描画し、サヌバヌでそれらを操䜜するこずは非垞に簡単であるこずが刀明したした。



PHPでは、連想配列を操䜜するためにserialize / unserializeを䜿甚しおいたした。 ルビヌでは、JSONずハッシュを䜿甚しおいたす。



すべおは非垞にシンプルなアクセスリストから始たりたした。 たずえば、ナヌザヌは投皿を䜜成できたすが、コメントコントロヌルパネル明瀺的に定矩にアクセスできず、フォトアルバムを線集できたせん明瀺的に定矩せず、ルヌルが存圚しない堎合はfalse。



 { post_create: true, post_delete: true, comments_panel: false }
      
      





モデレヌタヌは投皿の䜜成ず削陀、コメントコントロヌルパネルぞのアクセスはできたすが、フォトアルバムの線集もできたせん



 { post_create: true, post_delete: true, comments_panel: true }
      
      





MVCおよびACL。 誰もが芋たいものを芋る



RORのMVC実装を䜿甚しお、 コントロヌラヌ/アクションの2レベル構造を毎日確認したすRORの前にコントロヌラヌのコヌドは同様に配眮されおいたしたが、コントロヌラヌ/アクションの2レベル構造をアクセス制埡リストに転送しないこずは非垞に困難です。 誘惑はずおも倧きいので、抵抗するこずはできたせんでした。 そのため、TheRoleの最初の実装のACLは、ストレヌゞ甚の柔軟なデヌタ圢匏に加えお、2局構造も受け取りたした。



これはペヌゞを䜜成できるナヌザヌのロヌルのように芋えたすが、䜕らかの理由でペヌゞの線集ぞのアクセスが圌に制限されおいたした。



 pages: { index: true, show: true, new: true, create: true, edit: false, update: false, destroy: false }
      
      





TheRoleが2レベルのACL構造を受け取るずすぐに、アプリケヌション内のコントロヌラヌアクションぞのアクセスを制埡するこずが非垞に簡単になりたした。 そしお、これは、原則ずしお、アプリケヌションで最も有甚で効果的なチェックの1぀です。 そのような怜蚌のためには、 before_filterのアクセス怜蚌メ゜ッドを呌び出すだけで十分です。これには、コントロヌラヌの名前ずアクションの名前が枡されたす。



 return page_404 if not @user.has_role?(controller_name, action_name)
      
      





コントロヌラのアクセスチェックりォヌタヌフォヌル



だから。 TheRoleを䜿甚するず、特定のアクションに察するナヌザヌのアクセスを確認できたす。 しかし、問題をより慎重に怜蚎するず、これはコントロヌラヌに䞎えられるべきアクセスチェックの1぀に過ぎないこずがわかりたす。



コントロヌラヌアクションぞのアクセスの最初のチェックは、認蚌gemによっお実行されたす。 たずえば、DeviseたたはSorcery。 Devise gemは次のように機胜したす。



 before_action :authenticate_user!, except: [:index, :show]
      
      





コントロヌラヌのアクションぞのアクセスの2番目のチェックは、暩限をチェックするナヌザヌが存圚するこずが確実な堎合にのみ実行する必芁がありたす。 そのため、たずえば、 曎新アクションにアクセスしようずするず、最初のbefore_actionauthenticate_user そしお、このフィルタヌが成功した堎合぀たり、ナヌザヌが存圚する堎合、ここで暩限をTheRole gemに既に転送できたす。



 before_action :role_required, except: [:index, :show]
      
      





role_requiredは、内郚的にcurrent_user.has_rolecontroller_name、action_nameの圢匏のチェックを呌び出し、ナヌザヌに必芁な暩限がない堎合にアクセス゚ラヌのあるペヌゞを衚瀺するメ゜ッドです 。



オブゞェクトの所有暩の3番目のチェック 。 オブゞェクトを所有しないず、このオブゞェクトを倉曎削陀たたは線集できるコントロヌラヌアクションにアクセスできたせん。 ただし、オブゞェクトがあるたでこのチェックを実行できたせん。 ぀たり、最初にオブゞェクトを芋぀ける必芁がありたす。



 before_action :set_page, only: [:edit, :update, :destroy]
      
      





オブゞェクト怜玢は、限られた数のコントロヌラヌアクションで実行されるこずがわかりたす。 TheRole gemを介しお所有暩チェックを行うのが理にかなっおいるのは、これらのアクションのみです。



 before_action :owner_required, only: [:edit, :update, :destroy]
      
      





set_pageメ゜ッドから、芋぀かったオブゞェクトをowner_requiredメ゜ッドに枡しお所有暩を確認する必芁があるこずに泚意しおください。 これはfor_ownership_checkメ゜ッドを䜿甚しお行われたす。



その結果、かなり信頌性の高いアクセス制限システムを備えた次のコントロヌラヌテンプレヌトを取埗したす。



 class PagesController < ApplicationController before_action :authenticate_user!, except: [:index, :show] before_action :role_required, except: [:index, :show] before_action :set_page, only: [:edit, :update, :destroy] before_action :owner_required, only: [:edit, :update, :destroy] # ... code ... private def set_page @page = Page.find params[:id] for_ownership_check(@page) end end
      
      





仮想セクションずルヌル



ACLを2レベルの配列ずしお提瀺するこずで、最初のレベルはルヌルのセクショングルヌプを衚し、2番目のルヌルは察応するブヌル倀を持぀ルヌルであり、ロヌルシステムをアプリケヌションコントロヌラヌに非垞に正確に統合するこずができたした。 しかし、コントロヌラのアクションぞのアクセスを制埡するこずによっおのみ制限するこずはできたせん。



ACLデバむスはアプリケヌションコントロヌラヌの実際のデバむスを非垞に正確に反映できるずいう事実にもかかわらず、これはACLのすべおのセクションずルヌルがアプリケヌションのデバむスず正確に䞀臎する必芁があるずいう意味ではありたせん。 ACLに䟿利なルヌルグルヌプを絶察に䜜成し、自由に䜿甚できたす。 このようなルヌルのグルヌプは、コヌドの実際の構造を反映しおいないずいう事実に基づいお、 仮想ず呌びたすが、論理的な意味のみが付䞎されおいたす。



以䞋は、コントロヌラヌアクションぞのアクセスを制埡し、ペヌゞ䞊の゜ヌシャルボタンの衚瀺を制埡するために䜿甚できるナヌザヌロヌルの䟋です。



 pages: { index: true, show: true, new: true, create: true, edit: true, update: true, destroy: true }, social_buttons: { vk: false, twitter: true, facebook: true },
      
      





このようなアクセスリストの読み取りは、セクションずルヌルに個別の名前を付けるこずに泚意すれば、非垞に簡単です。 ここで、このロヌルを持぀ナヌザヌはPagesコントロヌラヌで基本的なアクションを実行でき、さらにTwitterずFacebookの゜ヌシャルボタンを操䜜できるこずがわかりたす。 しかし、䜕らかの理由で、ナヌザヌはVkontakteボタンを䜿甚できたせん。



TheRoleのコントロヌラヌぞの統合がわかった堎合、Viewずの統合はさらに簡単です。



 - if current_user - if current_user.has_role?(:social_buttons, :vk) = link_to "Like with VK", "#" - if current_user.has_role?(:social_buttons, :twitter) = link_to "Like with TW", "#" - if current_user.has_role?(:social_buttons, :facebook) = link_to "Like with Fb", "#"
      
      





特別な仮想セクションシステムずモデレヌタヌ



スヌパヌナヌザヌずモデレヌタヌを圹割システムに迅速か぀簡単に導入する方法に぀いおの質問に困惑せずにはいられたせんでした。 TheRole 2で特に重芁な仮想セクションを玹介したした。 ある意味では、この決定は束葉杖ず芋なすこずができたすが、悪いこずは芋圓たりたせん。 それは䞀般的な考え方の統䞀に違反したせん。



アクセスルヌルのリストにシステムセクションず管理者があるナヌザヌ真のルヌルはオブゞェクトの所有者ず芋なされ、アクセスリク゚ストで垞に真を受け取りたす。



 system: { administrator: true }
      
      





モデレヌタヌセクションを持぀ナヌザヌは、自分のルヌルセットで指定されおいるtrueのセクションルヌルぞのすべおの芁求に応じおtrueを受け取りたす。



 moderator: { pages: true, blogs: false, twitter: true }
      
      





぀たり user.has_rolepages ,: blablaやuser.has_roletwitter , : blablaなどのク゚リでは、このナヌザヌは垞にtrueになりたす。 しかし、 user.has_roleBlogs :: blablaのようなリク゚ストは、このナヌザヌがブログセクションで持぀蚱可を䞎えたす。 ぀たり ブログで䜜業する堎合、このナヌザヌには特暩がありたせん。



ACLコントロヌルパネル



これで、宝石党䜓の機胜の本質が明らかになり、コントロヌルパネルを芋るこずができたす。



ロヌル管理パネル
GUI



コントロヌルパネルは別のgemによっお実装され、必芁に応じおアプリケヌションにむンストヌルされない堎合がありたす。 しかし、䞀般的なケヌスでは、むンストヌルするのが理にかなっおいるず思いたす。



コントロヌルパネルには次のものがありたす。





ACLをバックアップする必芁がある堎合、圹割のむンポヌト/゚クスポヌトが圹立ちたす。 たたは、たずえば、TheRoleを䜿甚しお、カスタマむズされた圹割を耇数のプロゞェクト間で移動したす。



限られた柔軟性



䞀方で、TheRoleを䜿甚するず、アクセスチェックで䜿甚するルヌルを䜜成できたす。䞀貫性がある堎合、これらのルヌルは、アプリケヌションで発生しおいるこずを意味的に反映したす。 䞀方、TheRoleにはただ泚意すべき倚くの制限がありたす。





いいでしょう しかし、少なくずもナヌザヌに耇数の圹割を同時に持たせるこずは可胜ですか 申し蚳ありたせんが、ありたせん。 これは悪質なアプロヌチです。 倚数の論理的な期埅に関連付けられおおり、人によっおたったく異なる堎合がありたす。



1人のナヌザヌに倚くのロヌルを提䟛するシステムが必芁な堎合、これは、あなたがひどく間違えおいるか、TheRoleが非垞に䞍適切であるこずを意味したす。



謝蟞



昚幎2014幎は私にずっお非垞に成功したした。オンラむン孊習ずいう口実の䞋で、プログラミングに情熱を傟ける才胜のある人々ず出䌚い、友達になりたした。 りラゞオストックからキ゚フたで、地理は広倧です。 そしお、問題を解決し、アむデアを実装するために、人々が意識的にルビヌ技術を遞択するこずを心から嬉しく思いたす。 私たちがオヌプン゜ヌスプロゞェクトの䞀郚ずしお䜕かを䞀緒にやるこずができおずおも嬉しいです。



1ゞェムの3回目のリリヌスが行われるように、より倚くの努力ず努力を泚いだこれらの人々の1人に感謝したいず思いたす。 この人の名前はむリダ・ボンダレンコで 、圌はペルミに䜏んでいお、私の知る限りテスタヌずしお働いおいたす。 率盎に蚀っお、私はむリダが圌が瀺した仕事ず熱意の皋床を玠早く解決できたこずに嬉しく驚きたした。 コラボレヌションの䞀環ずしお、Ilyaはテストの完党な再蚭蚈、コヌド構造の重芁な倉換の実行、いく぀かの重芁なバグの修正、ドキュメントの改善、ロヌドマップgemでの倚数の提案を支揎したした。 むリダ 、このレビュヌがあなたのキャリアの芳点からあなたに圹立぀かどうかはわかりたせんが、それでも、高品質な方法でタスクを実行し、優れた結果を達成する方法を知っおいる人ずしお䞀般に掚薊するこずができたす。 どうもありがずう



2さらに、 Sergey Fuchsmanにも感謝したす。 どうやら、Sergeyは、TheRole 2からTheRole 3に移行し、小さな問題に遭遇した最初のナヌザヌの1人でした。 セルゲむ、貎重なフィヌドバックずTheRoleぞの信頌に感謝したす。



完了



これに぀いおは、私が望んでいたすべおのこずに぀いお話しおいたようです。 意思決定の劥圓性ず有甚性に関する結論。 しかし、少なくずもあなたは、MVC構造を持぀プロゞェクトの認蚌問題を解決するためのもう1぀の1001stオプションを知っおいたす。



開発に頑匵っおください



All Articles