Module: Joinable::ActsAsJoinable::ClassMethods

Includes:
Joinable::ActsAsPermissable::ClassMethods
Defined in:
lib/joinable/acts_as_joinable.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Joinable::ActsAsPermissable::ClassMethods

#find_with_privacy, #permission_sql_condition

Class Method Details

.extended(base) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/joinable/acts_as_joinable.rb', line 49

def self.extended(base)
  base.cattr_accessor :permissions, :component_permissions_hashes

  base.has_many :membership_invitations, :as => :joinable, :dependent => :destroy, :before_add => :add_initiator
base.has_many :membership_requests, :as => :joinable, :dependent => :destroy
  			base.has_many :memberships, :as => :joinable, :dependent => :destroy, :order => "id ASC", :before_remove => :add_initiator

  			base.has_many :invitees, :class_name => "User", :through => :membership_invitations, :source => :user
base.has_many :requestees, :class_name => "User", :through => :membership_requests, :source => :user
base.has_many :members, :class_name => "User", :through => :memberships, :source => :user

  			base.has_many :non_owner_memberships, :as => :joinable, :class_name => 'Membership', :conditions => "permissions NOT LIKE '%own%'"
  base.has_one :owner_membership, :as => :joinable, :class_name => 'Membership', :conditions => "permissions LIKE '%own%'"

  			base.has_many :permission_links, :as => :joinable, :dependent => :destroy

  			base.has_one :default_permission_set, :as => :joinable, :dependent => :destroy

  			base.after_create :add_owner_membership

  base.class_eval do
    # Return all *joinables* that a User is a member of with the appropriate permissions
    scope :with_permission, lambda {|user, permission| where(with_permission_sql(user, permission)) }

    #scope :open, lambda { where(default_permission_set_permission_exists_sql(joinable_type, joinable_id, 'find')) }

    # TODO: Why is this NULLS LAST? Probably because we want the results in some specific order when joined with users, but couldn't we order manually in the find?
    scope :with_member, lambda {|user| joins(:memberships).where(:memberships => {:user_id => (user.is_a?(User) ? user.id : user)}).order("memberships.created_at DESC NULLS LAST") }
  end

  base.accepts_nested_attributes_for :default_permission_set
  base.accepts_nested_attributes_for :membership_invitations, :allow_destroy => true
  base.accepts_nested_attributes_for :memberships, :allow_destroy => true, :reject_if => proc { |attributes| attributes['locked'] == 'true' }
end

Instance Method Details

#collaborator_permissionsObject



104
105
106
# File 'lib/joinable/acts_as_joinable.rb', line 104

def collaborator_permissions
  permissions - [:manage, :own]
end

#collaborator_permissions_stringObject

Member can view everything and modify everything except members



100
101
102
# File 'lib/joinable/acts_as_joinable.rb', line 100

def collaborator_permissions_string
  collaborator_permissions.join(" ")
end

#manager_permissions_stringObject

Member can view everything, modify everything, and manage membership



109
110
111
# File 'lib/joinable/acts_as_joinable.rb', line 109

def manager_permissions_string
  (permissions - [:own]).join(" ")
end

#owner_permissions_stringObject

Member started the joinable



114
115
116
# File 'lib/joinable/acts_as_joinable.rb', line 114

def owner_permissions_string
  permissions_string
end

#permissions_stringObject



84
85
86
# File 'lib/joinable/acts_as_joinable.rb', line 84

def permissions_string
  permissions.join(" ")
end

#viewer_permissionsObject



95
96
97
# File 'lib/joinable/acts_as_joinable.rb', line 95

def viewer_permissions
  permissions.select { |permission| permission == :find || permission.to_s.starts_with?("view") }
end

#viewer_permissions_stringObject

Simple Permission Strings - Permission strings for four basic levels of permissions - viewer, collaborator, manager, owner

Member can view everything but modify nothing



91
92
93
# File 'lib/joinable/acts_as_joinable.rb', line 91

def viewer_permissions_string
  viewer_permissions.join(" ")
end

#with_permission_sql(user, permission, options = {}) ⇒ Object

Returns the SQL necessary to find all joinables for which the user has a membership with a specific permission.

Permissions which require special handling:

  • find - In addition to memberships, invitations and default permission sets are checked for the permission. This is because

    a joinable should be able to be found once an invitation has been extended or if it is findable by default. (even if the user isn't a member of it).
    
  • view_* - This is a class of permissions that start with the word ‘view’. When determining if a user can view any aspect of a joinable, we also check

    if the project is open.
    
  • join - This is a faux permission. A user has permission to join a joinable if they have an invitation to view it or if it is viewable by default.

  • collaborate - This is a faux permission. A user has permission to collaborate if they have any additional permissions above the standard viewer permissions.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/joinable/acts_as_joinable.rb', line 134

def with_permission_sql(user, permission, options = {})
  permission = permission.to_sym

  case user
  when String
    user_id = user
  when
    user_id = user.id
  end

  joinable_type = options[:type_column] || name
  joinable_id = options[:id_column] || table_name + ".id"

  if permission == :find
    "#{membership_permission_exists_sql(user_id, joinable_type, joinable_id, 'find')} OR #{membership_invitation_permission_exists_sql(user_id, joinable_type, joinable_id, 'find')} OR #{default_permission_set_permission_exists_sql(joinable_type, joinable_id, 'find')}"
  elsif permission.to_s.starts_with?('view')
    "#{membership_permission_exists_sql(user_id, joinable_type, joinable_id, permission)} OR #{default_permission_set_permission_exists_sql(joinable_type, joinable_id, permission)}"
  elsif permission == :join
    "#{membership_invitation_permission_exists_sql(user_id, joinable_type, joinable_id, 'view')} OR #{default_permission_set_permission_exists_sql(joinable_type, joinable_id, 'view')}"
  elsif permission.to_s.starts_with?('join_and_')
    default_permission_set_permission_exists_sql(joinable_type, joinable_id, permission.to_s.gsub('join_and_', ''))
  elsif permission == :collaborate
    "EXISTS (SELECT id FROM memberships WHERE memberships.joinable_type = '#{joinable_type}' AND memberships.joinable_id = #{joinable_id} AND memberships.user_id = #{user_id} AND memberships.permissions && '{#{(collaborator_permissions - viewer_permissions).join(",")}}')"
  else
    membership_permission_exists_sql(user_id, joinable_type, joinable_id, permission)
  end
end