social_stream 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/app/controllers/api_controller.rb +1 -1
  2. data/app/controllers/contacts_controller.rb +1 -1
  3. data/app/controllers/conversations_controller.rb +5 -5
  4. data/app/controllers/groups_controller.rb +1 -0
  5. data/app/controllers/likes_controller.rb +17 -5
  6. data/app/controllers/messages_controller.rb +3 -1
  7. data/app/controllers/profiles_controller.rb +4 -0
  8. data/app/controllers/representations_controller.rb +12 -1
  9. data/app/controllers/tags_controller.rb +15 -0
  10. data/app/controllers/users_controller.rb +3 -0
  11. data/app/helpers/activities_helper.rb +13 -6
  12. data/app/models/activity.rb +53 -52
  13. data/app/models/activity_object.rb +2 -0
  14. data/app/models/actor.rb +85 -19
  15. data/app/models/avatar.rb +2 -1
  16. data/app/models/like.rb +28 -13
  17. data/app/models/permission.rb +7 -7
  18. data/app/models/profile.rb +1 -1
  19. data/app/models/relation/custom.rb +111 -0
  20. data/app/models/relation/public.rb +42 -0
  21. data/app/models/relation.rb +1 -89
  22. data/app/models/sphere.rb +7 -0
  23. data/app/models/tie.rb +65 -52
  24. data/app/models/tie_activity.rb +38 -0
  25. data/app/views/activities/_new.html.erb +4 -4
  26. data/app/views/activities/_options.html.erb +2 -2
  27. data/app/views/actors/_actor.html.erb +0 -0
  28. data/app/views/avatars/index.html.erb +5 -2
  29. data/app/views/comments/_new.html.erb +2 -2
  30. data/app/views/contacts/index.html.erb +5 -1
  31. data/app/views/conversations/edit.html.erb +4 -0
  32. data/app/views/conversations/index.html.erb +5 -1
  33. data/app/views/conversations/show.html.erb +4 -0
  34. data/app/views/frontpage/index.html.erb +4 -0
  35. data/app/views/groups/_sidebar_index.html.erb +7 -42
  36. data/app/views/groups/index.html.erb +3 -0
  37. data/app/views/groups/new.html.erb +3 -0
  38. data/app/views/groups/show.html.erb +7 -0
  39. data/app/views/layouts/_account.html.erb +16 -0
  40. data/app/views/layouts/_footer.html.erb +1 -1
  41. data/app/views/layouts/_header.erb +7 -22
  42. data/app/views/layouts/_representation.html.erb +25 -12
  43. data/app/views/layouts/application.html.erb +6 -3
  44. data/app/views/layouts/frontpage.html.erb +1 -1
  45. data/app/views/likes/create.js.erb +1 -1
  46. data/app/views/likes/destroy.js.erb +1 -1
  47. data/app/views/messages/new.html.erb +7 -5
  48. data/app/views/profiles/_profile.html.erb +20 -0
  49. data/app/views/profiles/edit.html.erb +42 -0
  50. data/app/views/profiles/show.html.erb +4 -0
  51. data/app/views/profiles/update.js.erb +5 -0
  52. data/app/views/subjects/_toolbar_profile_menu_tie_options.html.erb +3 -1
  53. data/app/views/ties/_new.html.erb +1 -1
  54. data/app/views/users/index.html.erb +4 -0
  55. data/app/views/users/show.html.erb +5 -0
  56. data/config/locales/en.yml +54 -1
  57. data/config/routes.rb +3 -1
  58. data/lib/generators/social_stream/install_generator.rb +2 -1
  59. data/lib/generators/social_stream/templates/migration.rb +23 -27
  60. data/lib/generators/social_stream/templates/public/images/btn/error.png +0 -0
  61. data/lib/generators/social_stream/templates/public/images/btn/info.png +0 -0
  62. data/lib/generators/social_stream/templates/public/images/btn/like.png +0 -0
  63. data/lib/generators/social_stream/templates/public/images/btn/nolike.png +0 -0
  64. data/lib/generators/social_stream/templates/public/images/btn/success.png +0 -0
  65. data/lib/generators/social_stream/templates/public/images/btn/warning.png +0 -0
  66. data/lib/generators/social_stream/templates/public/javascripts/ajax.paginate.js +12 -19
  67. data/lib/generators/social_stream/templates/public/javascripts/jquery.validate.js +1 -1
  68. data/lib/generators/social_stream/templates/public/javascripts/main.js +20 -10
  69. data/lib/generators/social_stream/templates/public/stylesheets/default/base.css +21 -4
  70. data/lib/generators/social_stream/templates/public/stylesheets/default/header.css +8 -3
  71. data/lib/generators/social_stream/templates/relations.yml +7 -13
  72. data/lib/social_stream/ability.rb +39 -20
  73. data/lib/social_stream/controllers/helpers.rb +6 -0
  74. data/lib/social_stream/models/object.rb +8 -4
  75. data/lib/social_stream/models/subject.rb +6 -0
  76. data/lib/social_stream/rails.rb +6 -3
  77. data/lib/social_stream/version.rb +1 -1
  78. data/lib/tasks/db/populate.rake +11 -1
  79. data/social_stream.gemspec +7 -8
  80. data/spec/controllers/comments_controller_spec.rb +6 -2
  81. data/spec/controllers/posts_controller_spec.rb +93 -5
  82. data/spec/controllers/profiles_controller_spec.rb +58 -1
  83. data/spec/controllers/representations_controller_spec.rb +51 -0
  84. data/spec/controllers/users_controller_spec.rb +28 -0
  85. data/spec/dummy/config/relations.yml +7 -13
  86. data/spec/dummy/db/schema.rb +2 -13
  87. data/spec/factories/tie.rb +1 -1
  88. data/spec/models/activity_spec.rb +28 -67
  89. data/spec/models/profile_spec.rb +38 -0
  90. data/spec/models/tie_activity_spec.rb +88 -31
  91. data/spec/models/tie_spec.rb +20 -14
  92. data/spec/support/db.rb +8 -10
  93. data/spec/support/migrations.rb +24 -0
  94. metadata +74 -59
@@ -43,10 +43,10 @@
43
43
  #
44
44
  # Available functions are:
45
45
  #
46
- # +tie+:: apply the permission to the established tie only.
46
+ # nil:: apply the permission to the established tie only.
47
47
  #
48
48
  # Example: if the _friend_ relation has the permission
49
- # <tt>create activity tie</tt>, the _friend_ can create activities
49
+ # <tt>create activity nil</tt>, the _friend_ can create activities
50
50
  # attached to this tie only. _Bob_ can create activities only at _Alice_'s
51
51
  # _friend_ level.
52
52
  #
@@ -90,17 +90,17 @@ class Permission < ActiveRecord::Base
90
90
  # The SQL and ARel conditions for permission queries
91
91
  ParameterConditions = {
92
92
  :table => {
93
- 'tie' =>
93
+ nil =>
94
94
  "ties_as.sender_id = ties.sender_id AND ties_as.receiver_id = ties.receiver_id AND ties_as.relation_id = ties.relation_id",
95
95
  'weak_ties' =>
96
- "ties_as.sender_id = ties.sender_id AND ties_as.receiver_id = ties.receiver_id AND relations.lft BETWEEN relations_as.lft AND relations_as.rgt",
96
+ "ties_as.sender_id = ties.sender_id AND ties_as.receiver_id = ties.receiver_id AND (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 || '/%'))",
97
97
  'star_ties' =>
98
98
  "ties_as.sender_id = ties.sender_id AND ties_as.relation_id = ties.relation_id",
99
99
  'weak_star_ties' =>
100
- "ties_as.sender_id = ties.sender_id AND relations.lft BETWEEN relations_as.lft AND relations_as.rgt"
100
+ "ties_as.sender_id = ties.sender_id AND (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 || '/%'))"
101
101
  },
102
102
  :arel => {
103
- 'tie' => lambda { |as, t|
103
+ nil => lambda { |as, t|
104
104
  # The same sender, receiver and relation
105
105
  as[:sender_id].eq(t.sender_id).and(
106
106
  as[:receiver_id].eq(t.receiver_id)).and(
@@ -141,7 +141,7 @@ class Permission < ActiveRecord::Base
141
141
  else
142
142
  ParameterConditions[:table].inject([]){ |result, pc|
143
143
  result <<
144
- sanitize_sql([ "#{ pc.last } AND permissions.function = ?", pc.first ])
144
+ "#{ pc.last } AND #{ sanitize_sql('permissions.function' => pc.first) }"
145
145
  }.join(" OR ")
146
146
  end
147
147
  end
@@ -1,6 +1,6 @@
1
1
  class Profile < ActiveRecord::Base
2
2
  belongs_to :actor
3
-
3
+
4
4
  accepts_nested_attributes_for :actor
5
5
 
6
6
  validates_presence_of :actor_id
@@ -0,0 +1,111 @@
1
+ # When a new {SocialStream::Models::Subject subject} is created, a initial set
2
+ # of relations is created for him. Afterwards, the {SocialStream::Models::Subject subject}
3
+ # can customize them and adapt them to his own preferences.
4
+ #
5
+ # Default relations are defined at config/relations.yml
6
+ #
7
+ class Relation::Custom < Relation
8
+ # Default relations are defined in this configuration file
9
+ CONFIG = File.join(::Rails.root, 'config', 'relations.yml')
10
+
11
+ # This is weird. We must call #inspect before has_ancestry for Relation::Custom
12
+ # to recognize STI
13
+ inspect
14
+ has_ancestry
15
+
16
+ belongs_to :sphere
17
+ has_one :actor, :through => :sphere
18
+
19
+ validates_presence_of :name, :sphere_id
20
+
21
+ after_create :initialize_tie
22
+
23
+ class << self
24
+ # Relations configuration
25
+ def config
26
+ @config ||= YAML.load_file(CONFIG)
27
+ end
28
+
29
+ def defaults_for(actor)
30
+ cfg_rels = config[actor.subject_type.underscore]
31
+
32
+ if cfg_rels.nil?
33
+ raise "Undefined relations for subject type #{ actor.subject_type }. Please, add an entry to #{ CONFIG }"
34
+ end
35
+
36
+ rels = {}
37
+
38
+ cfg_rels.each_pair do |name, cfg_rel|
39
+ raise("Must associatiate relation #{ cfg_rel['name'] } to a sphere") if cfg_rel['sphere'].blank?
40
+ sphere = actor.spheres.find_or_create_by_name(cfg_rel['sphere'])
41
+
42
+ rels[name] =
43
+ create! :sphere => sphere,
44
+ :receiver_type => cfg_rel['receiver_type'],
45
+ :name => cfg_rel['name']
46
+
47
+ if (ps = cfg_rel['permissions']).present?
48
+ ps.each do |p|
49
+ rels[name].permissions <<
50
+ Permission.find_or_create_by_action_and_object_and_function(*p)
51
+ end
52
+ end
53
+ end
54
+
55
+ # Parent, relations must be set after creation
56
+ # FIXME: Can fix with ruby 1.9 and ordered hashes
57
+ cfg_rels.each_pair do |name, cfg_rel|
58
+ rels[name].update_attribute(:parent, rels[cfg_rel['parent']]) if cfg_rel['parent'].present?
59
+ end
60
+
61
+ rels.values
62
+ end
63
+
64
+ # A relation in the top of a strength hierarchy
65
+ def strongest
66
+ roots
67
+ end
68
+ end
69
+
70
+ # Compare two relations
71
+ def <=> rel
72
+ return -1 if rel.is_a?(Public)
73
+
74
+ if ancestor_ids.include?(rel.id)
75
+ 1
76
+ elsif rel.ancestor_ids.include?(id)
77
+ -1
78
+ else
79
+ 0
80
+ end
81
+ end
82
+
83
+ # Other relations below in the same hierarchy that this relation
84
+ def weaker
85
+ descendants
86
+ end
87
+
88
+ # Relations below or at the same level of this relation
89
+ def weaker_or_equal
90
+ subtree
91
+ end
92
+
93
+ # Other relations above in the same hierarchy that this relation
94
+ def stronger
95
+ ancestors
96
+ end
97
+
98
+ # Relations above or at the same level of this relation
99
+ def stronger_or_equal
100
+ path
101
+ end
102
+
103
+
104
+ private
105
+
106
+ # Create reflexive tie for the owner of this {Relation::Custom custom relation}
107
+ def initialize_tie
108
+ ties.create! :sender => sphere.actor,
109
+ :receiver => sphere.actor
110
+ end
111
+ end
@@ -0,0 +1,42 @@
1
+ class Relation::Public < Relation
2
+ attr_accessor :actor
3
+
4
+ after_create :initialize_tie
5
+
6
+ scope :actor, lambda { |a|
7
+ joins(:ties).merge(Tie.sent_by(a))
8
+ }
9
+
10
+ class << self
11
+ def default_for(actor)
12
+ create! :actor => actor
13
+ end
14
+
15
+ # The {Relation::Public} belonging to actor
16
+ def of(actor)
17
+ actor(actor).first
18
+ end
19
+ end
20
+
21
+ # A {Relation::Public public relation} is always the weakest
22
+ def <=>(relation)
23
+ 1
24
+ end
25
+
26
+ # The name of public relation
27
+ def name
28
+ I18n.t('relation.public.name')
29
+ end
30
+
31
+ # Are we supporting custom permissions for {Relation::Public}? Not by the moment.
32
+ def allow?(user, action, object)
33
+ action == 'read' && object == 'activity'
34
+ end
35
+
36
+ private
37
+
38
+ def initialize_tie
39
+ ties.create! :sender => actor,
40
+ :receiver => actor
41
+ end
42
+ end
@@ -3,14 +3,6 @@
3
3
  # resources (transactions, lending and borrowing), messages or conversations,
4
4
  # physical connection and affiliation to same organizations.
5
5
  #
6
- # = Default relations
7
- #
8
- # When a new {SocialStream::Models::Subject subject} is created, a initial set
9
- # of relations is created for him. Afterwards, the {SocialStream::Models::Subject subject}
10
- # can customize them and adapt them to his own preferences.
11
- #
12
- # Default relations are defined at config/relations.yml
13
- #
14
6
  # = Strength hierarchies
15
7
  #
16
8
  # Relations are arranged in strength hierarchies, denoting that some ties between
@@ -27,66 +19,18 @@
27
19
  # See the documentation of {Permission} for more details on permission definition.
28
20
  #
29
21
  class Relation < ActiveRecord::Base
30
- # The actor this relation belongs to
31
- attr_accessor :actor
32
-
33
- # Default relations are defined in this configuration file
34
- CONFIG = File.join(::Rails.root, 'config', 'relations.yml')
35
-
36
- acts_as_nested_set
37
-
38
22
  scope :mode, lambda { |st, rt|
39
23
  where(:sender_type => st, :receiver_type => rt)
40
24
  }
41
25
 
42
- validates_presence_of :name
43
-
44
26
  has_many :relation_permissions, :dependent => :destroy
45
27
  has_many :permissions, :through => :relation_permissions
46
28
 
47
29
  has_many :ties, :dependent => :destroy
48
30
 
49
31
  before_create :initialize_sender_type
50
- after_create :initialize_ties
51
32
 
52
33
  class << self
53
- # Relations configuration
54
- def config
55
- @config ||= YAML.load_file(CONFIG)
56
- end
57
-
58
- def defaults_for(actor)
59
- cfg_rels = config[actor.subject_type.underscore]
60
-
61
- if cfg_rels.nil?
62
- raise "Undefined relations for subject type #{ actor.subject_type }. Please, add an entry to #{ CONFIG }"
63
- end
64
-
65
- rels = {}
66
-
67
- cfg_rels.each_pair do |name, cfg_rel|
68
- rels[name] =
69
- Relation.create! :actor => actor,
70
- :receiver_type => cfg_rel['receiver_type'],
71
- :name => cfg_rel['name']
72
-
73
- if (ps = cfg_rel['permissions']).present?
74
- ps.each do |p|
75
- rels[name].permissions <<
76
- Permission.find_or_create_by_action_and_object_and_function(*p)
77
- end
78
- end
79
- end
80
-
81
- # Parent, relations must be set after creation
82
- # FIXME: Can fix with ruby 1.9 and ordered hashes
83
- cfg_rels.each_pair do |name, cfg_rel|
84
- rels[name].update_attribute(:parent, rels[cfg_rel['parent']]) if cfg_rel['parent'].present?
85
- end
86
-
87
- rels.values
88
- end
89
-
90
34
  # Get relation from object, if possible
91
35
  #
92
36
  # Options::
@@ -120,31 +64,6 @@ class Relation < ActiveRecord::Base
120
64
  normalize(r, options).id
121
65
  end
122
66
  end
123
-
124
- # A relation in the top of a strength hierarchy
125
- def strongest
126
- root
127
- end
128
- end
129
-
130
- # Other relations below in the same hierarchy that this relation
131
- def weaker
132
- descendants
133
- end
134
-
135
- # Relations below or at the same level of this relation
136
- def weaker_or_equal
137
- self_and_descendants
138
- end
139
-
140
- # Other relations above in the same hierarchy that this relation
141
- def stronger
142
- ancestors
143
- end
144
-
145
- # Relations above or at the same level of this relation
146
- def stronger_or_equal
147
- self_and_ancestors
148
67
  end
149
68
 
150
69
  # Relation class scoped in the same mode that this relation
@@ -160,12 +79,5 @@ class Relation < ActiveRecord::Base
160
79
 
161
80
  self.sender_type = actor.subject_type
162
81
  end
163
-
164
- # Create reflexive ties for this actor
165
- def initialize_ties
166
- return if actor.blank?
167
-
168
- ties.create! :sender => actor,
169
- :receiver => actor
170
- end
171
82
  end
83
+
@@ -0,0 +1,7 @@
1
+ class Sphere < ActiveRecord::Base
2
+ belongs_to :actor
3
+
4
+ has_many :relations
5
+
6
+ validates_presence_of :name
7
+ end
data/app/models/tie.rb CHANGED
@@ -1,16 +1,19 @@
1
- # A tie is a link between two {Actor actors} with a {Relation relation}.
1
+ # A {Tie} is a link between two {Actor Actors} with a {Relation}.
2
2
  #
3
- # The first {Actor actor} is the sender of the {Tie tie}. The second {Actor actor}
4
- # is the receiver of the {Tie tie}.
3
+ # The first {Actor} is the sender of the {Tie}. The second {Actor}
4
+ # is the receiver of the {Tie}.
5
5
  #
6
6
  # = {Tie Ties} and {Activity activities}
7
- # {Activity Activities} are attached to {Tie ties}.
8
- # * The sender of the tie is the target of the {Activity}.
9
- # The wall-profile of an {Actor} is composed by the resources assigned to
10
- # the {Tie Ties} in which the {Actor} is the sender.
11
- # * The receiver {Actor} of the {Tie} is the author of the {Activity}.
7
+ # {Activity Activities} are attached to {Tie ties}. When _Alice_ post in _Bob_'s wall,
8
+ # the {Activity} is attached to the {Tie} from _Alice_ to _Bob_
9
+ #
10
+ # * The sender of the {Tie} is the author of the {Activity}.
12
11
  # It is the user that uploads a resource to the website or the social entity that
13
- # originates the {Activity}.
12
+ # originates the {Activity} (for example: add as contact).
13
+ #
14
+ # * The receiver {Actor} of the {Tie} is the receiver of the {Activity}.
15
+ # The {Activity} will appear in the wall of the receiver, depending on the permissions
16
+ #
14
17
  # * The {Relation} sets up the mode in which the {Activity} is shared.
15
18
  # It sets the rules, or {Permission Permissions}, by which {Actor} have access
16
19
  # to the {Activity}.
@@ -35,7 +38,6 @@
35
38
  # = Scopes
36
39
  # There are several scopes defined:
37
40
  #
38
- # original:: ties created by actors. It excludes ties created in the weaker set.
39
41
  # sent_by(actor):: ties whose sender is actor
40
42
  # received_by(actor):: ties whose receiver is actor
41
43
  # sent_or_received_by(actor):: the union of the former
@@ -45,13 +47,12 @@
45
47
  # is replied if there is a tie from b to a
46
48
  #
47
49
  class Tie < ActiveRecord::Base
48
- attr_accessor :message
49
- attr_accessor :relation_permissions
50
-
51
50
  # Facilitates relation assigment along with find_relation callback
52
51
  attr_writer :relation_name
53
52
  # Facilitates new relation permissions assigment along with find_or build_relation callback
54
- attr_reader :relation_permissions
53
+ attr_accessor :relation_sphere, :relation_permissions
54
+ # Send a message when this tie is created
55
+ attr_accessor :message
55
56
 
56
57
  belongs_to :sender,
57
58
  :class_name => "Actor",
@@ -65,9 +66,7 @@ class Tie < ActiveRecord::Base
65
66
  has_many :tie_activities, :dependent => :destroy
66
67
  has_many :activities, :through => :tie_activities
67
68
 
68
- scope :original, where(:original => true)
69
-
70
- scope :recent, order("#{ quoted_table_name }.created_at DESC")
69
+ scope :recent, order("ties.created_at DESC")
71
70
 
72
71
  scope :sent_by, lambda { |a|
73
72
  where(:sender_id => Actor.normalize_id(a))
@@ -94,17 +93,25 @@ class Tie < ActiveRecord::Base
94
93
  where("ties.sender_id = ties_2.receiver_id AND ties.receiver_id = ties_2.sender_id")
95
94
  }
96
95
 
96
+ scope :replying, lambda { |tie|
97
+ where(:sender_id => tie.receiver_id).
98
+ where(:receiver_id => tie.sender_id)
99
+ }
100
+
97
101
  scope :following, lambda { |a|
98
102
  where(:receiver_id => Actor.normalize_id(a)).
99
103
  joins(:relation => :permissions).merge(Permission.follow)
100
104
  }
101
105
 
106
+ scope :public_relation, lambda {
107
+ joins(:relation).where('relations.type' => 'Relation::Public')
108
+ }
109
+
102
110
  validates_presence_of :sender_id, :receiver_id, :relation
103
111
 
104
112
  before_validation :find_or_build_relation
105
113
 
106
114
  before_create :save_relation
107
- after_create :complete_weak_set
108
115
  after_create :create_activity
109
116
  after_create :send_message
110
117
 
@@ -185,12 +192,6 @@ class Tie < ActiveRecord::Base
185
192
  # We get the set of ties that are allowing certain permission
186
193
  #
187
194
 
188
- scope :with_permissions, lambda { |action, object|
189
- joins(:relation => :permissions).
190
- where('permissions.action' => action).
191
- where('permissions.object' => object)
192
- }
193
-
194
195
  # Given a given permission (action, object), the access_set are the set of ties that grant that permission.
195
196
  scope :access_set, lambda { |tie, action, object|
196
197
  with_permissions(action, object).
@@ -201,13 +202,13 @@ class Tie < ActiveRecord::Base
201
202
  query =
202
203
  select("DISTINCT ties.*").
203
204
  from("ties INNER JOIN relations ON relations.id = ties.relation_id, ties as ties_as INNER JOIN relations AS relations_as ON relations_as.id = ties_as.relation_id INNER JOIN relation_permissions ON relations_as.id = relation_permissions.relation_id INNER JOIN permissions ON permissions.id = relation_permissions.permission_id").
204
- where("permissions.action = ?", action).
205
- where("permissions.object = ?", object)
205
+ where("permissions.action" => action).
206
+ where("permissions.object" => object)
206
207
 
207
208
  conds = Permission.parameter_conditions
208
209
  # FIXME: Patch to support public activities
209
210
  if action == 'read' && object == 'activity'
210
- conds = sanitize_sql([ "( #{ conds } ) OR relations.name = ?", "public" ])
211
+ conds = "( #{ conds } ) OR #{ sanitize_sql('relations.type' => 'Relation::Public') }"
211
212
  end
212
213
 
213
214
  query.where(conds)
@@ -229,13 +230,38 @@ class Tie < ActiveRecord::Base
229
230
  end
230
231
 
231
232
  # Does this tie allows user to perform action on object?
232
- def allows?(user, action, object)
233
- # FIXME: Patch to support public activities
234
- return true if relation.name == 'public' && action == 'read' && object == 'activity'
233
+ #
234
+ # We allow all actions on reflexive ties
235
+ def allow?(user, action, object)
236
+ return true if Actor.normalize_id(user) == sender_id && reflexive?
237
+
238
+ # FIXME: Patch to support public activities.
239
+ if relation.is_a?(Relation::Public)
240
+ return relation.allow?(user, action, object)
241
+ end
235
242
 
236
243
  allowing(user, action, object).any?
237
244
  end
238
245
 
246
+ scope :with_permissions, lambda { |action, object|
247
+ joins(:relation => :permissions).
248
+ where('permissions.action' => action).
249
+ where('permissions.object' => object)
250
+ }
251
+
252
+ # All the ties that are allowed to follow activities from this tie
253
+ def followers
254
+ followers = Tie.received_by(sender).with_permissions('follow', nil)
255
+
256
+ unless relation.is_a?(Relation::Public)
257
+ allowed = access_set('read', 'activity').map(&:receiver_id)
258
+
259
+ followers = followers.sent_by(allowed)
260
+ end
261
+
262
+ followers
263
+ end
264
+
239
265
  private
240
266
 
241
267
  # Before validation callback
@@ -243,8 +269,8 @@ class Tie < ActiveRecord::Base
243
269
  def find_or_build_relation
244
270
  return if find_relation || relation_name.blank?
245
271
 
246
- self.relation = Relation.new :name => relation_name,
247
- :actor => sender
272
+ self.relation = Relation::Custom.new :name => relation_name,
273
+ :sphere => nil
248
274
 
249
275
  relation.permission_ids = relation_permissions
250
276
  end
@@ -265,34 +291,21 @@ class Tie < ActiveRecord::Base
265
291
  end
266
292
 
267
293
 
268
- # After create callback
269
- # Creates ties with weaker relations in the strength hierarchy of this tie
270
- def complete_weak_set
294
+ # After create callback to create related {Activity}
295
+ def create_activity
271
296
  return if reflexive?
272
297
 
273
- relation.weaker.each do |r|
274
- if relation_set(:relations => r).blank?
275
- t = relation_set.build :relation => r,
276
- :original => false
277
- t.save!
278
- end
279
- end
298
+ Activity.create! :_tie => self, :activity_verb => ActivityVerb[contact_verb]
280
299
  end
281
-
282
- def create_activity
283
- return if ! original? || reflexive?
284
300
 
285
- Activity.create! :_tie => self, :activity_verb => ActivityVerb[contact_verb]
301
+ def contact_verb
302
+ replied? ? "make-friend" : "follow"
286
303
  end
287
-
304
+
288
305
  # Send a message to the receiver of the tie
289
306
  def send_message
290
- if original? && message.present?
307
+ if message.present?
291
308
  sender.send_message(receiver, message, I18n.t("activity.verb.#{ contact_verb }.#{ receiver.subject_type }.message", :name => sender.name))
292
309
  end
293
310
  end
294
-
295
- def contact_verb
296
- replied? ? "make-friend" : "follow"
297
- end
298
311
  end
@@ -1,4 +1,42 @@
1
1
  class TieActivity < ActiveRecord::Base
2
2
  belongs_to :activity
3
3
  belongs_to :tie
4
+
5
+ after_create :disseminate
6
+
7
+ private
8
+
9
+ # Make a copy to all the ties that are both interesed and allowed to reach the activity
10
+ def disseminate
11
+ return unless original?
12
+
13
+ followers = tie.followers
14
+
15
+ # FIXME: here we need to check moderation and diffussion of the received activity.
16
+ #
17
+ # Sometimes, diffussion is not required, i.e. when the sender adds the receiver as contact
18
+ # Other times, the receiver must explicitly allow to post to her wall, and the dissemination permissions
19
+ # can control who else related with the receiver should receive the activity
20
+ receiver_ties =
21
+ Tie.
22
+ with_permissions('create', 'activity').
23
+ replying(tie)
24
+
25
+ if receiver_ties.present?
26
+ followers |= receiver_ties
27
+
28
+ # Disseminate to the followers of the receiver
29
+ receiver_ties.each do |t|
30
+ followers |= t.followers
31
+ end
32
+ end
33
+
34
+ # All the ties following the activities attached to this tie, allowed to read
35
+ # this activity
36
+ followers.each do |t|
37
+ self.class.create!(:activity_id => activity_id,
38
+ :tie => t,
39
+ :original => false)
40
+ end
41
+ end
4
42
  end
@@ -1,4 +1,4 @@
1
- <% if receiver.active_ties_for(current_subject).any? %>
1
+ <% if receiver.activity_ties_for?(current_subject) %>
2
2
  <% content_for :javascript do %>
3
3
 
4
4
  securityImage = "<%= escape_javascript(image_tag('btn/btn_security.png', :id => 'security_image', :alt => 'security')) %>";
@@ -11,14 +11,14 @@
11
11
 
12
12
  <div id="activities_header" class="content_size">
13
13
  <%= form_for Post.new(:text => t('activity.input'),
14
- :_activity_tie_id => receiver.active_ties_for(current_subject).first.id),
14
+ :_activity_tie_id => receiver.activity_ties_for(current_subject).first.id),
15
15
  :remote => true do |f| %>
16
16
  <%= f.text_field :text, :id => "input_activities", :size => 85 %>
17
17
  <div id="activities_share_btn">
18
18
 
19
- <% if receiver.active_ties_for(current_subject).count > 1 %>
19
+ <% if receiver.activity_ties_for(current_subject).count > 1 %>
20
20
  <div id="securities">
21
- <%= f.select :_activity_tie_id, receiver.active_ties_for(current_subject).sort{ |t, u| t.relation <=> u.relation }.map{ |t| [ t.relation_name, t.id ] }, {}, :id => 'security' %>
21
+ <%= f.select :_activity_tie_id, receiver.activity_ties_for(current_subject).sort{ |t, u| t.relation <=> u.relation }.map{ |t| [ t.relation_name, t.id ] }, {}, :id => 'security' %>
22
22
  </div>
23
23
  <% else %>
24
24
  <%= f.hidden_field :_activity_tie_id %>
@@ -1,11 +1,11 @@
1
1
  <div class="activity_options">
2
2
  <ul class="activity_options" >
3
3
  <li><div class="post_time_ago"><%= t('time.ago', :time => time_ago_in_words(activity.created_at)) %></div></li>
4
- <% if activity.is_root? && activity.receiver.sent_ties_allowing(current_subject, 'create', 'activity').any? %>
4
+ <% if activity.is_root? && activity.receiver.activity_ties_for?(current_subject) %>
5
5
  <li><div class="verb_comment"> · <%= link_to t('activity.to_comment'), "#", :class => "to_comment" %> </div></li>
6
6
  <% end %>
7
7
  <li><div class="verb_like" id="like_<%= dom_id(activity) %>"> · <%= link_like(activity)%></div></li>
8
- <% if activity.direct_object.present? %>
8
+ <% if activity.direct_object.present? && !activity.direct_object.is_a?(Actor) %>
9
9
  <li><div class="verb_delete"> · <%= link_to t('activity.delete'), activity.direct_object , :confirm => t('confirm_delete', :scope => activity.direct_object.class.to_s.underscore), :method => :delete, :remote => true %> </div></li>
10
10
  <% end %>
11
11
  </ul>
File without changes
@@ -5,6 +5,9 @@
5
5
  <%= javascript_include_tag 'avatars.js' %>
6
6
  <% end %>
7
7
 
8
+ <% content_for :title do%>
9
+ <%= current_subject.name %>
10
+ <% end%>
8
11
  <% content_for :sidebar do %>
9
12
  <%= render :partial => 'home/sidebar' %>
10
13
  <% end %>
@@ -18,7 +21,7 @@
18
21
  <div class="space_center"></div>
19
22
  <div class="space_center"></div>
20
23
  <% unless(@avatars.empty? || (@avatars.first.present? && @avatars.first.id.blank?)) %>
21
- <h2>Use your saved avatars ...</h2>
24
+ <h2><%=t('avatar.text.use') %></h2>
22
25
  <div class="space_center"></div>
23
26
  <div class="space_center"></div>
24
27
  <div class="avatars">
@@ -46,7 +49,7 @@
46
49
  <br class="clearfloat" />
47
50
  <div class="space_center"></div>
48
51
  <div class="space_center"></div>
49
- <h2>... our upload a new one</h2>
52
+ <h2><%=t('avatar.text.new') %></h2>
50
53
  <% else %>
51
54
  <h2><%= t('avatar.new') %></h2>
52
55
  <% end %>
@@ -1,8 +1,8 @@
1
- <% if activity.receiver.sent_ties_allowing(current_subject, 'create', 'activity').any? %>
1
+ <% if activity.receiver.activity_ties_for?(current_subject) %>
2
2
  <div class="activity_new_comment">
3
3
  <%= form_for Comment.new(:text => t('comment.input'),
4
4
  :_activity_tie_id =>
5
- activity.receiver.sent_ties_allowing(current_subject, 'create', 'activity').first.id,
5
+ activity.receiver.activity_ties_for(current_subject).first.id,
6
6
  :_activity_parent_id => activity.id),
7
7
  :remote => true do |f| %>
8
8
  <%= f.hidden_field :_activity_tie_id %>