Permalink
Browse files

Simplify permissions

  • Loading branch information...
1 parent 69ffa73 commit 9ee92c6299ce513ad495a2ea2666a87b05558a0b @atd atd committed Jul 12, 2011
@@ -31,7 +31,6 @@ def link_like_params(object)
def new_activity(receiver)
return Activity.new unless user_signed_in?
- Activity.new :contact_id => current_subject.contact_to!(receiver).id,
- :relation_ids => current_subject.activity_relations(receiver, :from => :receiver).map(&:id)
+ Activity.new :contact_id => current_subject.contact_to!(receiver).id
end
end
@@ -1,16 +1,16 @@
module PermissionsHelper
DEFAULT_PERMISSIONS =
[
- [ "read", "activity", "same_and_lower_levels" ],
- [ "create", "activity", "same_level" ],
- [ "follow", nil, nil],
- [ "represent", nil, nil]
+ [ "read", "activity" ],
+ [ "create", "activity" ],
+ [ "follow", nil ],
+ [ "represent", nil ]
]
def default_permissions
@default_permissions ||=
DEFAULT_PERMISSIONS.map{ |p|
- Permission.find_or_create_by_action_and_object_and_function *p
+ Permission.find_or_create_by_action_and_object *p
}
end
end
View
@@ -204,22 +204,30 @@ def notify
def allow?(subject, action)
return false if contact.blank?
- # We do not support private activities by now
- return false if relation_ids.blank?
-
case action
when 'create'
return false if contact.sender_id != Actor.normalize_id(subject)
- rels = Relation.normalize(relation_ids)
+ if relation_ids.present?
+ rels = Relation.normalize(relation_ids)
+
+ foreign_rels = rels.select{ |r| r.actor_id != contact.sender_id }
- foreign_rels = rels.select{ |r| r.actor_id != contact.sender_id }
+ # Only posting to own relations
+ return true if foreign_rels.blank?
- # Only posting to own relations
- return true if foreign_rels.blank?
+ return Relation.
+ allow(subject, action, 'activity', :in => foreign_rels).all.size == foreign_rels.size
+ else
+ if contact.reflexive?
+ return true
+ else
+ relation_ids = receiver.relation_customs.allow(sender, 'create', 'activity')
+
+ return relation_ids.present?
+ end
+ end
- return Relation.
- allow(subject, action, 'activity', :in => foreign_rels).all.size == foreign_rels.size
when 'read'
return true if [contact.sender_id, contact.receiver_id].include?(Actor.normalize_id(subject)) || relations.select{ |r| r.is_a?(Relation::Public) }.any?
when 'update'
@@ -230,9 +238,7 @@ def allow?(subject, action)
end
Relation.
- allow(subject, action, 'activity').
- where('relations.id' => relation_ids).
- any?
+ allow?(subject, action, 'activity', :in => self.relation_ids, :public => false)
end
# Can subject delete the object of this activity?
View
@@ -293,48 +293,22 @@ def represented_by?(subject)
any?
end
- # The relations that allow attaching an activity to them. This method is used for caching
- def active_relations
- @active_relations ||= { :sender => {}, :receiver => {} }
- end
-
# An {Activity} can be shared with multiple {audicences Audience}, which corresponds to a {Relation}.
#
# This method returns all the {relations Relation} that this actor can use to broadcast an Activity
#
- # Options:
- # from:: limit the relations to one side, from the :sender or the :receiver of the activity
#
def activity_relations(subject, options = {})
return relations if Actor.normalize(subject) == self
- case options[:from]
- when :sender
- sender_activity_relations(subject)
- when :receiver
- receiver_activity_relations(subject)
- else
- sender_activity_relations(subject) +
- receiver_activity_relations(subject)
- end
+ Array.new
end
# Are there any activity_relations present?
def activity_relations?(*args)
activity_relations(*args).any?
end
- # Relations from this actor that can be read by subject
- def sender_activity_relations(subject)
- active_relations[:sender][subject] ||=
- Relation.allow(subject, 'read', 'activity', :owner => self)
- end
-
- def receiver_activity_relations(subject)
- active_relations[:receiver][subject] ||=
- Relation.allow(self, 'create', 'activity', :owner => subject)
- end
-
# Is this {Actor} allowed to create a comment on activity?
#
# We are allowing comments from everyone signed in by now
View
@@ -1,5 +1,5 @@
-# SocialStream provides a sophisticated and powerful system of permissions based on the {Relation relations}
-# of the social network.
+# SocialStream provides a system of permissions based on the {Relation relations}
+# of the social network as roles.
#
# = Permissions and Relations
#
@@ -13,9 +13,9 @@
#
# = Permissions description
#
-# Permissions are composed by *action*, *objective* and *function*. Action and objective
+# Permissions are composed by *action* and *object*. Action and object
# are typical in content management systems, e.g. <tt>create activity</tt>,
-# <tt>update tie</tt>, <tt>read post</tt>. *function* is a new parameter for social networks
+# <tt>update tie</tt>, <tt>read post</tt>.
#
# == Actions
#
@@ -32,33 +32,8 @@
#
# +activity+:: all the objects in a wall: posts, comments
#
-# Other objectives currently not implemented could be +tie+, +post+, +comment+ or +message+
+# Other objects currently not implemented could be +tie+, +post+, +comment+ or +message+
#
-# == Functions
-#
-# Function is a novel feature. It supports applying the permission to other related relations and ties.
-# It is required because the set of ties changes while {SocialStream::Models::Subject subjects } build their network.
-# Besides {SocialStream::Models::Subject subjects} can describe and
-# customize their own relations and permissions.
-#
-# Available functions are:
-#
-# +same_level+:: the permission applies to all the objects in same relation
-#
-# Example: the _friend_ relation has the permission
-# <tt>read tie same_level</tt>. If _Alice_ has a _friend_ tie with
-# _Bob_, she is granting him access to read all the contacts of type _friend_
-##
-# +same_and_lower_levels+:: apply the permission to all the related objects attached to a relation weaker
-# or equal than this.#
-#
-# Example: if the _member_ relation of a group has the permission
-# <tt>create activity same_and_lower_levels</tt>, its members
-# can also create activities attached to the weaker relations of
-# _acquaintance_ and _public_.
-# This means than a group _member_ can create activities at different
-# levels of the sphere, and therefore, with different levels of
-# access.
#
class Permission < ActiveRecord::Base
has_many :relation_permissions, :dependent => :destroy
@@ -68,50 +43,13 @@ class Permission < ActiveRecord::Base
scope p, where(:action => p) # scope :represent, where(:action => 'represent')
end
- RelationConditions = {
- 'same_level' =>
- "relations.id = relations_as.id",
- 'same_and_lower_levels' =>
- "(relations.id = relations_as.id OR relations.ancestry = relations_as.id || '' OR relations.ancestry = (relations_as.ancestry || '/' || relations_as.id) OR relations.ancestry LIKE (relations_as.id || '/%') OR relations.ancestry LIKE (relations_as.ancestry || '/' || relations_as.id || '/%')) OR (relations.actor_id = relations_as.actor_id AND relations.type = 'Relation::Public')"
- }
-
- class << self
- # Builds SQL conditions based on {RelationConditions}
- def relation_conditions
- RelationConditions.inject([]){ |result, pc|
- result <<
- "(#{ pc.last }) AND #{ sanitize_sql('permissions_as.function' => pc.first) }"
- }.join(" OR ")
- end
- end
-
# An explanation of the permissions. Type can be brief or detailed.
- # If detailed, description includes details about the relation
+ # If detailed, description includes more information about the relation
def description(type, relation = nil)
- options = ( relation.present? ? description_options(relation) : {} )
+ options = {}
+ options[:relation] = relation.name if relation.present?
- I18n.t "permission.description.#{ type }.#{ action }.#{ object || "nil" }.#{ function || "nil" }",
+ I18n.t "permission.description.#{ type }.#{ action }.#{ object || "nil" }",
options
end
-
- private
-
- def description_options(relation)
- {
- :public => I18n.t('relation_public.name')
- }.tap do |h|
- case function
- when NilClass, "same_level"
- h[:relation] = relation.name
- when "same_and_lower_levels"
- h[:relations] = relation.
- weaker_or_equal.
- sort.
- map(&:name).
- join(", ")
-
- end
- end
-
- end
end
View
@@ -30,6 +30,7 @@ class Relation < ActiveRecord::Base
has_many :permissions, :through => :relation_permissions
has_many :ties, :dependent => :destroy
+ has_many :contacts, :through => :ties
scope :mode, lambda { |st, rt|
where(:sender_type => st, :receiver_type => rt)
@@ -76,59 +77,34 @@ def normalize_id(r, options = {})
#
# Options:
# in:: Limit possible relations to a set
- # owner:: The owner of the relations
# public_relations:: include also {Relation::Public} whose activities can always be read
def allow(subject, action, object, options = {})
- # The case when the owner == subject is special,
- # all the permissions are granted to the owner of the relations
- if options[:owner].present? && Actor.normalize(options[:owner]) == Actor.normalize(subject)
- rels = subject.relations
+ q =
+ select("DISTINCT relations.*").
+ joins(:contacts).
+ joins(:permissions)
- if options[:in].present?
- rels = rels & options[:in]
- end
-
- rels
- end
-
- # Relation conditions
- # Some relations can have permissions that grant permissions to other relations
- # through Relation#function
- conds = Permission.relation_conditions
-
- # Permission conditions
- # Set the permission conditions
- conds = "( #{ conds } ) AND #{ sanitize_sql('permissions_as.action' => action) } AND #{ sanitize_sql('permissions_as.object' => object) }"
+ conds =
+ Permission.arel_table[:action].eq(action).and(Permission.arel_table[:object].eq(object))
# Relation::Public permissions cannot be customized yet
if action == 'read' && object == 'activity' && (options[:public].nil? || options[:public])
- conds =
- "( #{ conds } ) OR #{ sanitize_sql('relations.type' => 'Relation::Public') }"
- end
-
- # subject conditions
- #
- # Relation permissions are granted to the contact receiver.
- # However, relation owners have all the permissions
- conds = "( ( #{ conds } ) AND #{ sanitize_sql('contacts_as.receiver_id' => Actor.normalize_id(subject)) } ) OR #{ sanitize_sql('relations.actor_id' => Actor.normalize_id(subject)) }"
-
- # Add owner condition
- if options[:owner].present?
- conds = "( #{ conds } ) AND #{ sanitize_sql('relations.actor_id' => Actor.normalize_id(options[:owner])) }"
+ conds = conds.or(Relation.arel_table[:type].eq('Relation::Public'))
end
# Add in condition
if options[:in].present?
- conds = "( #{ conds } ) AND #{ sanitize_sql('relations.id' => Relation.normalize_id(Array(options[:in]))) }"
+ conds = conds.and(Relation.arel_table[:id].in(Relation.normalize_id(Array(options[:in]))))
end
- select("DISTINCT relations.*").
- from("relations, contacts AS contacts_as INNER JOIN ties AS ties_as ON contacts_as.id = ties_as.contact_id INNER JOIN relations AS relations_as ON relations_as.id = ties_as.relation_id INNER JOIN relation_permissions AS relation_permissions_as ON relations_as.id = relation_permissions_as.relation_id INNER JOIN permissions AS permissions_as ON permissions_as.id = relation_permissions_as.permission_id").
- where(conds)
+ # subject conditions
+ conds = conds.and(Contact.arel_table[:receiver_id].eq(Actor.normalize_id(subject)))
+
+ q.where(conds)
end
def allow?(*args)
- allow(*args).any?
+ allow(*args).to_a.any?
end
end
@@ -42,7 +42,7 @@ def defaults_for(actor)
if (ps = cfg_rel['permissions']).present?
ps.each do |p|
rels[name].permissions <<
- Permission.find_or_create_by_action_and_object_and_function(*p)
+ Permission.find_or_create_by_action_and_object(*p)
end
end
end
@@ -19,7 +19,9 @@
</div>
<div id="activities_share_btn">
+<% if current_subject == receiver %>
<div id="securities"><%= select_tag :_relation_ids, options_for_select(current_subject.activity_relations(receiver).sort.map{ |r| [ r.name, r.id ] }), :id => 'security', :multiple => nil %></div>
<%= submit_tag(t('share'), :class => "myButtonBlue", :id => "masterSubmitButton") %>
+<% end %>
</div>
<% end %>
@@ -1,7 +1,7 @@
<div class="activity_options">
<ul class="activity_options" >
<li><div class="post_time_ago"><%= t('time.ago', :time => time_ago_in_words(activity.created_at)) %></div></li>
- <% if activity.is_root? && user_signed_in? && current_subject.activity_relations?(activity.receiver, :in => activity.relations) %>
+ <% if activity.is_root? && user_signed_in? %>
<li><div class="verb_comment"> · <%= link_to t('activity.to_comment'), "#", :class => "to_comment" %> </div></li>
<% end %>
<li><div class="verb_like" id="like_<%= dom_id(activity) %>"> · <%= link_like(activity)%></div></li>
@@ -5,10 +5,4 @@
<%= f.hidden_field :_contact_id %>
<%= render :partial => object.class.to_s.tableize+'/fields' , :locals => {:f => f} %>
-
- <% if current_subject != receiver %>
- <% current_subject.activity_relations(receiver, :from => :receiver).each do |r| %>
- <%= f.hidden_field "_relation_ids][", :value => r.id %>
- <% end %>
- <% end %>
<% end %>
Oops, something went wrong.

0 comments on commit 9ee92c6

Please sign in to comment.