私はrBoardというフォーラムシステムを実装しています。コードはhttp://github.com/radar/rboardに表示されます。私は実装しようとしていたパーミッションコードの難しさに達しました。私は、この問題を解決するために、すべてを知っていて、思いやりのあるスタックオーバーフローに目を向けることに決めました。ユーザーの権限に基づいてフォーラムを見つける
関連情報は以下のようなものを次のとおりです。
Categoryモデル
class Category < ActiveRecord::Base
has_many :permissions
has_many :groups, :through => :permissions
has_many :forums
end
フォーラムモデル
class Forum < ActiveRecord::Base
has_many :permissions
has_many :groups, :through => :permissions
belongs_to :category
end
グループモデル
class Group < ActiveRecord::Base
has_many :group_users
has_many :users, :through => :group_users
belongs_to :owner, :class_name => "User"
end
許可モデル
class Permission < ActiveRecord::Base
belongs_to :forum
belongs_to :category
belongs_to :group
end
ユーザモデル
class User < ActiveRecord::Base
include Rboard::Permissions
has_many :group_users
# Note: I am using nested_has_many_through
has_many :groups, :through => :group_users
has_many :permissions, :through => :groups
end
権限モジュール
module Rboard::Permissions
THINGS = ['forum', 'category']
def self.included(klass)
klass.class_eval do
# Here we can pass an object to check if the user or any the user's groups
# has permissions on that particular option.
def overall_permissions(thing = nil)
conditions = if thing.nil?
THINGS.map do |t|
"permissions.#{t}_id " + (thing.nil? ? " IS NULL" : "= #{thing.id}") + " OR permissions.#{t}_id IS NULL"
end.join(" AND ")
else
association = thing.class.to_s.downcase
"permissions.#{association}_id = #{thing.id} OR permissions.#{association}_id IS NULL"
end
permissions.all(:conditions => conditions)
end
def can?(action, thing = nil)
permissions = overall_permissions(thing)
!!permissions.detect { |p| p.send("can_#{action}") }
end
end
end
end
Hこれをopefullyすれば、パーミッションテーブルのフィールドはcan_see_forum
のようになります。余分なフィールドはforum_id
,category_id
およびdefault
です(デフォルトは現在使用されていません)
私が知りたいことは、グループが見ることのできるフォーラムをすべて見つけることです。一般に、forum_idが設定されている場合、その権限が適用されます。 forum_idまたはcategory_idを指定せずにそのグループに対して1つのアクセス権しかない場合は、すべてのものに対してグローバルであると見なされます。私は完全にここに迷っています。