social_stream-base 0.22.4 → 0.23.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/app/controllers/activities_controller.rb +14 -12
  2. data/app/controllers/api_controller.rb +0 -13
  3. data/app/controllers/frontpage_controller.rb +0 -6
  4. data/app/models/activity.rb +21 -61
  5. data/app/models/actor.rb +4 -8
  6. data/app/models/audience.rb +2 -0
  7. data/app/models/comment.rb +2 -1
  8. data/app/models/group.rb +0 -2
  9. data/app/models/relation.rb +5 -1
  10. data/app/models/relation/custom.rb +17 -4
  11. data/app/models/tie.rb +0 -2
  12. data/app/models/user.rb +0 -2
  13. data/app/views/activities/_options.html.erb +1 -1
  14. data/app/views/activities/index.atom.builder +48 -0
  15. data/app/views/activity_objects/_activity_object.atom.erb +1 -0
  16. data/config/locales/en.yml +8 -0
  17. data/config/locales/es.yml +8 -0
  18. data/config/routes.rb +0 -8
  19. data/lib/rails/social_stream.rb +1 -1
  20. data/lib/social_stream-base.rb +5 -0
  21. data/lib/social_stream/ability/base.rb +4 -16
  22. data/lib/social_stream/activity_streams.rb +39 -0
  23. data/lib/social_stream/activity_streams/subtype.rb +11 -0
  24. data/lib/social_stream/activity_streams/supertype.rb +12 -0
  25. data/lib/social_stream/base/dependencies.rb +2 -0
  26. data/lib/social_stream/base/engine.rb +6 -0
  27. data/lib/social_stream/base/version.rb +1 -1
  28. data/lib/social_stream/models/object.rb +5 -0
  29. data/lib/social_stream/models/subject.rb +1 -1
  30. data/lib/social_stream/models/subtype.rb +2 -0
  31. data/lib/social_stream/models/supertype.rb +2 -0
  32. data/social_stream-base.gemspec +2 -0
  33. data/spec/controllers/activities_controller_spec.rb +18 -0
  34. data/spec/controllers/frontpage_controller_spec.rb +0 -5
  35. data/spec/models/activity_wall_spec.rb +96 -0
  36. data/spec/models/post_authorization_spec.rb +370 -0
  37. data/spec/models/post_spec.rb +0 -2
  38. data/spec/models/relation_spec.rb +22 -0
  39. data/spec/social_stream_activity_streams_spec.rb +16 -0
  40. data/spec/social_stream_spec.rb +1 -1
  41. metadata +27 -8
  42. data/app/assets/images/logos/actor/remote_subject.png +0 -0
  43. data/app/assets/images/logos/actor/remote_user.png +0 -0
  44. data/app/controllers/subjects_controller.rb +0 -7
  45. data/app/views/api/activity_atom_feed.atom.builder +0 -40
  46. data/app/views/frontpage/host_meta.xml.builder +0 -11
  47. data/spec/models/activity_authorization_spec.rb +0 -354
@@ -1,18 +1,20 @@
1
- class ActivitiesController < InheritedResources::Base
2
- actions :index
3
-
4
- respond_to :js
5
-
6
- protected
7
-
8
- def collection
9
- rel = params[:section].to_i if params[:section].present?
10
-
1
+ class ActivitiesController < ApplicationController
2
+ def index
11
3
  # should be activities.page(params[:page], :count => { :select => 'activity.id', :distinct => true }) but it is not working in Rails 3.0.3
12
4
  @activities ||= profile_subject.
13
5
  wall(:profile,
14
- :for => current_subject,
15
- :relation => rel).
6
+ :for => current_subject).
16
7
  page(params[:page])
8
+
9
+ respond_to do |format|
10
+ format.js
11
+ format.atom
12
+ end
13
+ end
14
+
15
+ def show
16
+ activity = Activity.find(params[:id])
17
+
18
+ redirect_to activity.direct_object || activity.receiver_subject
17
19
  end
18
20
  end
@@ -22,17 +22,4 @@ class ApiController < ApplicationController
22
22
 
23
23
  redirect_to :controller => :users, :action => :show, :format => params[:format], :id => params[:id], :auth_token => params[:auth_token]
24
24
  end
25
-
26
- def activity_atom_feed
27
- @subject = Actor.find_by_slug!(params[:id])
28
- # FIXME: why? check with Victor
29
- @subject ||= current_user
30
-
31
- @activities = @subject.wall(:home).page(params[:page]).per(10)
32
-
33
- respond_to do |format|
34
- format.atom
35
- end
36
- end
37
-
38
25
  end
@@ -7,12 +7,6 @@ class FrontpageController < ApplicationController
7
7
  end
8
8
  end
9
9
 
10
- # Webfinger protocol
11
- # http://code.google.com/p/webfinger/
12
- def host_meta
13
- end
14
-
15
-
16
10
  private
17
11
 
18
12
  def redirect_user_to_home
@@ -197,8 +197,8 @@ class Activity < ActiveRecord::Base
197
197
  case verb
198
198
  when "follow", "make-friend", "like"
199
199
  I18n.t "activity.verb.#{ verb }.#{ receiver.subject_type }.title",
200
- :subject => view.link_name(sender_subject),
201
- :contact => view.link_name(receiver_subject)
200
+ :subject => view.link_name(sender_subject),
201
+ :contact => view.link_name(receiver_subject)
202
202
  when "post", "update"
203
203
  if sender == receiver
204
204
  view.link_name sender_subject
@@ -212,6 +212,25 @@ class Activity < ActiveRecord::Base
212
212
  end.html_safe
213
213
  end
214
214
 
215
+ # Title for activity streams
216
+ def stream_title
217
+ # FIXMEEEEEEEEEEEEEEEEE
218
+ object = ( direct_object.present? ?
219
+ ( direct_object.is_a?(SocialStream::Models::Subject) ?
220
+ direct_object.name :
221
+ direct_object.title ) :
222
+ receiver.name )
223
+
224
+ I18n.t "activity.stream.title.#{ verb }",
225
+ :author => sender_subject.name,
226
+ :activity_object => object
227
+ end
228
+
229
+ # TODO: detailed description of activity
230
+ def stream_content
231
+ stream_title
232
+ end
233
+
215
234
  def notificable?
216
235
  is_root? or ['post','update'].include?(root.verb)
217
236
  end
@@ -245,65 +264,6 @@ class Activity < ActiveRecord::Base
245
264
  [parent] + siblings
246
265
  end
247
266
 
248
- # Is subject allowed to perform action on this {Activity}?
249
- def allow?(subject, action)
250
- return false if author.blank?
251
-
252
- case action
253
- when 'create'
254
- return false if subject.blank? || author_id != Actor.normalize_id(subject)
255
-
256
- rels = Relation.normalize(relation_ids)
257
-
258
- own_rels = rels.select{ |r| r.actor_id == author_id }
259
- # Consider Relation::Single as own_relations
260
- own_rels += rels.select{ |r| r.is_a?(Relation::Single) }
261
-
262
- foreign_rels = rels - own_rels
263
-
264
- # Only posting to own relations or allowed to post to foreign relations
265
- return foreign_rels.blank? && own_rels.present? ||
266
- foreign_rels.present? && Relation.allow(subject,
267
- action,
268
- 'activity',
269
- :in => foreign_rels).
270
- all.size == foreign_rels.size
271
-
272
- when 'read'
273
- return true if relations.select{ |r| r.is_a?(Relation::Public) }.any?
274
-
275
- return false if subject.blank?
276
-
277
- return true if [author_id, owner_id].include?(Actor.normalize_id(subject))
278
- when 'update'
279
- return true if [author_id, owner_id].include?(Actor.normalize_id(subject))
280
- when 'destroy'
281
- # We only allow destroying to sender and receiver by now
282
- return [author_id, owner_id].include?(Actor.normalize_id(subject))
283
- end
284
-
285
- Relation.
286
- allow?(subject, action, 'activity', :in => self.relation_ids, :public => false)
287
- end
288
-
289
- # Can subject delete the object of this activity?
290
- def delete_object_by?(subject)
291
- subject.present? &&
292
- direct_object.present? &&
293
- ! direct_object.is_a?(Actor) &&
294
- ! direct_object.class.ancestors.include?(SocialStream::Models::Subject) &&
295
- allow?(subject, 'destroy')
296
- end
297
-
298
- # Can subject edit the object of this activity?
299
- def edit_object_by?(subject)
300
- subject.present? &&
301
- direct_object.present? &&
302
- ! direct_object.is_a?(Actor) &&
303
- ! direct_object.class.ancestors.include?(SocialStream::Models::Subject) &&
304
- allow?(subject, 'update')
305
- end
306
-
307
267
  # Is this activity public?
308
268
  def public?
309
269
  relation_ids.include? Relation::Public.instance.id
@@ -136,13 +136,11 @@ class Actor < ActiveRecord::Base
136
136
  after_create :create_initial_relations
137
137
 
138
138
  after_create :save_or_create_profile
139
-
140
- class << self
141
- def find_by_webfinger!(link)
142
- link =~ /(acct:)?(.*)@/
143
139
 
144
- find_by_slug! $2
145
- end
140
+ # FIXME SocialStream::ActivityStreams::Supertype should take precedence over
141
+ # SocialStream::ActivityStreams::Subtype
142
+ def as_object_type
143
+ subtype_instance.as_object_type
146
144
  end
147
145
 
148
146
  #Returning the email address of the model if an email should be sent for this object (Message or Notification).
@@ -590,5 +588,3 @@ class Actor < ActiveRecord::Base
590
588
  mailbox.inbox(:unread => true).count(:id, :distinct => true)
591
589
  end
592
590
  end
593
-
594
- ActiveSupport.run_load_hooks(:actor, Actor)
@@ -7,3 +7,5 @@ class Audience < ActiveRecord::Base
7
7
  belongs_to :activity
8
8
  belongs_to :relation
9
9
  end
10
+
11
+ ActiveSupport.run_load_hooks(:audience, Audience)
@@ -12,7 +12,8 @@ class Comment < ActiveRecord::Base
12
12
  end
13
13
 
14
14
  def parent_post
15
- self.post_activity.parent.direct_object
15
+ _activity_parent_id && _activity_parent.direct_object ||
16
+ post_activity.parent.direct_object
16
17
  end
17
18
 
18
19
  def title
@@ -57,5 +57,3 @@ class Group < ActiveRecord::Base
57
57
  end
58
58
  end
59
59
  end
60
-
61
- ActiveSupport.run_load_hooks(:group, Group)
@@ -181,6 +181,11 @@ class Relation < ActiveRecord::Base
181
181
  self.class.positive_names.include?(self.class.to_s)
182
182
  end
183
183
 
184
+ # Does this relation include the follow permission?
185
+ def follow?
186
+ permissions.follow.any?
187
+ end
188
+
184
189
  private
185
190
 
186
191
  # Before create callback
@@ -190,4 +195,3 @@ class Relation < ActiveRecord::Base
190
195
  self.sender_type = actor.subject_type
191
196
  end
192
197
  end
193
-
@@ -5,8 +5,11 @@
5
5
  # Default relations are defined at config/relations.yml
6
6
  #
7
7
  class Relation::Custom < Relation
8
- # Default relations are defined in this configuration file
9
- CONFIG = File.join(::Rails.root, 'config', 'relations.yml')
8
+ # Default relations shipped with Social Stream
9
+ DEFAULT = {}
10
+
11
+ # Default relations are re-defined in this configuration file
12
+ CONFIG_FILE = File.join(::Rails.root, 'config', 'relations.yml')
10
13
 
11
14
  # This is weird. We must call #inspect before has_ancestry for Relation::Custom
12
15
  # to recognize STI
@@ -21,14 +24,14 @@ class Relation::Custom < Relation
21
24
  class << self
22
25
  # Relations configuration
23
26
  def config
24
- @config ||= YAML.load_file(CONFIG)
27
+ @config ||= build_config
25
28
  end
26
29
 
27
30
  def defaults_for(actor)
28
31
  cfg_rels = config[actor.subject_type.underscore]
29
32
 
30
33
  if cfg_rels.nil?
31
- raise "Undefined relations for subject type #{ actor.subject_type }. Please, add an entry to #{ CONFIG }"
34
+ raise "Undefined relations for subject type #{ actor.subject_type }. Please, add an entry to #{ CONFIG_FILE }"
32
35
  end
33
36
 
34
37
  rels = {}
@@ -62,6 +65,14 @@ class Relation::Custom < Relation
62
65
  def strongest
63
66
  roots
64
67
  end
68
+
69
+ private
70
+
71
+ # Gets the default relations defined in DEFAULT and updates the values
72
+ # from the CONFIG_FILE configuration file
73
+ def build_config
74
+ DEFAULT.merge YAML.load_file(CONFIG_FILE)
75
+ end
65
76
  end
66
77
 
67
78
  # Compare two relations
@@ -110,3 +121,5 @@ class Relation::Custom < Relation
110
121
  end
111
122
  end
112
123
  end
124
+
125
+ ActiveSupport.run_load_hooks(:relation_custom, Relation::Custom)
@@ -156,5 +156,3 @@ class Tie < ActiveRecord::Base
156
156
  contact.sender_id == relation.actor_id
157
157
  end
158
158
  end
159
-
160
- ActiveSupport.run_load_hooks(:tie, Tie)
@@ -153,5 +153,3 @@ class User < ActiveRecord::Base
153
153
 
154
154
  end
155
155
  end
156
-
157
- ActiveSupport.run_load_hooks(:user, User)
@@ -22,7 +22,7 @@
22
22
  </div>
23
23
  <% end %>
24
24
 
25
- <% if activity.delete_object_by?(current_subject) %>
25
+ <% if activity.direct_object && can?(:destroy, activity.direct_object) %>
26
26
  <div class="verb_delete">
27
27
  · <%= link_to t('activity.delete'), activity.direct_object , :confirm => t('confirm_delete',
28
28
  :scope => activity.direct_object.class.to_s.underscore), :method => :delete,
@@ -0,0 +1,48 @@
1
+ atom_feed('xmlns:activity' => 'http://activitystrea.ms/spec/1.0/') do |feed|
2
+ feed.link :rel => 'next', :href => url_for(:only_path => false, :page => params[:page].to_i + 1, :format => :atom)
3
+ if params[:page].to_i > 1
4
+ feed.link :rel => 'previous', :href => url_for(:only_path => false, :page => params[:page].to_i - 1, :format => :atom)
5
+ end
6
+
7
+ #FIXME find a way to decouple the view from here
8
+
9
+ if defined? SocialStream::Ostatus
10
+ feed.link :rel => 'hub', :href => SocialStream::Ostatus.hub
11
+ feed.link rel: 'salmon', href: salmon_url(profile_subject.slug)
12
+ end
13
+
14
+ feed.title(t 'activity.stream.atom_title', subject: profile_subject.name)
15
+ feed.updated(@activities.first.present? ? @activities.first.updated_at : Time.now)
16
+
17
+ feed.author do
18
+ feed.name(profile_subject.name)
19
+ feed.uri("acct:#{ profile_subject.slug }@#{ request.host_with_port }")
20
+ feed.tag!('activity:object-type', profile_subject.as_object_type.to_s)
21
+ end
22
+
23
+ @activities.each do |activity|
24
+ feed.entry(activity) do |entry|
25
+ entry.title(activity.stream_title)
26
+ entry.summary(activity.direct_object.try(:description))
27
+
28
+ entry.author do |a|
29
+ a.name(activity.sender.name)
30
+ a.uri("acct:#{ activity.sender.slug }@#{ request.host_with_port }")
31
+ a.tag!('activity:object-type', activity.sender.as_object_type.to_s)
32
+ end
33
+
34
+ #TODO Ostatus mentions:
35
+ # entry.link rel: mentioned, href: "acct:#{ mentioned.slug }@#{ host_with_port }"
36
+
37
+ entry.tag!('activity:verb', activity.verb)
38
+
39
+ if (obj = activity.direct_object).present?
40
+ entry.tag!('activity:object') do |act_obj|
41
+ act_obj.title(obj.title)
42
+ act_obj.tag!('activity:object-type', obj.as_object_type.to_s)
43
+ act_obj.published(obj.created_at)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -62,6 +62,14 @@ en:
62
62
  group: "Members of %{receiver}"
63
63
  user: "Contacts of %{receiver}"
64
64
  sending: "Sending"
65
+ stream:
66
+ atom_title: "Activity Stream from %{subject}"
67
+ title:
68
+ follow: "%{author} added %{activity_object} as contact"
69
+ like: "%{author} likes %{activity_object}"
70
+ make-friend: "%{author} also added %{activity_object} as contact"
71
+ post: "%{author} posted %{activity_object}"
72
+ updated: "%{author} posted %{activity_object}"
65
73
  title: "Activities"
66
74
  to_comment: "Comment"
67
75
  unlike: "I do not like anymore"
@@ -61,6 +61,14 @@ es:
61
61
  group: "Integrantes de %{receiver}"
62
62
  user: "Contactos de %{receiver}"
63
63
  sending: "Enviando"
64
+ stream:
65
+ atom_title: "Actividades de %{subject}"
66
+ title:
67
+ follow: "%{author} añadió a %{activity_object} como contacto"
68
+ like: "A %{author} le gusta %{activity_object}"
69
+ make-friend: "%{author} también añadió a %{activity_object} como contacto"
70
+ post: "%{author} publicó %{activity_object}"
71
+ updated: "%{author} actualizó %{activity_object}"
64
72
  title: "Actividades"
65
73
  to_comment: "Comentar"
66
74
  unlike: "Ya no me gusta"
@@ -101,21 +101,13 @@ Rails.application.routes.draw do
101
101
  match 'api/user/:id' => 'api#users', :as => :api_user
102
102
  match 'api/me' => 'api#users', :as => :api_me
103
103
  match 'api/me/home/' => 'api#activity_atom_feed', :format => 'atom', :as => :api_my_home
104
- match 'api/user/:id/public' => 'api#activity_atom_feed', :format => 'atom', :as => :api_user_activities
105
104
 
106
105
  match 'api/me/contacts' => 'contacts#index', :format => 'json', :as => :api_contacts
107
106
  match 'api/subjects/:s/contacts' => 'contacts#index', :format => 'json', :as => :api_subject_contacts
108
107
  ##/API##
109
-
110
108
 
111
109
  #Background tasks
112
110
  constraints SocialStream::Routing::Constraints::Resque.new do
113
111
  mount Resque::Server, :at => "/resque"
114
112
  end
115
-
116
- # Webfinger
117
- match '.well-known/host-meta',:to => 'frontpage#host_meta'
118
-
119
- # Find subjects by slug
120
- match 'subjects/lrdd/:id' => 'subjects#lrdd', :as => 'subject_lrdd'
121
113
  end
@@ -5,7 +5,7 @@ class ActionDispatch::Http::UploadedFile
5
5
  def initialize_with_magic(*args, &block)
6
6
  initialize_without_magic(*args, &block)
7
7
 
8
- if (unix_file = `which file`.chomp).present? && File.exists?(unix_file)
8
+ if (unix_file = `which file`.try(:chomp)).present? && File.exists?(unix_file)
9
9
  `#{ unix_file } -v 2>&1` =~ /^file-(.*)$/
10
10
  version = $1
11
11
 
@@ -4,6 +4,11 @@ require 'social_stream/base/dependencies'
4
4
  # Provides your Rails application with social network and activity stream support
5
5
  module SocialStream
6
6
  autoload :Ability, 'social_stream/ability'
7
+ autoload :ActivityStreams, 'social_stream/activity_streams'
8
+ module ActivityStreams
9
+ autoload :Supertype, 'social_stream/activity_streams/supertype'
10
+ autoload :Subtype, 'social_stream/activity_streams/subtype'
11
+ end
7
12
  autoload :D3, 'social_stream/d3'
8
13
  autoload :Populate, 'social_stream/populate'
9
14
  autoload :Relations, 'social_stream/relations'
@@ -37,40 +37,28 @@ module SocialStream
37
37
  end
38
38
 
39
39
  can :create, Comment do |c|
40
- c._activity_parent.allow?(subject, 'read')
40
+ can? :read, c.parent_post
41
41
  end
42
42
 
43
43
  can :read, Comment do |c|
44
- c.post_activity.allow?(subject, 'read')
44
+ can? :read, c.parent_post
45
45
  end
46
46
 
47
47
  can :update, Comment do |c|
48
- c.post_activity.allow?(subject, 'update')
48
+ can? :update, c.parent_post
49
49
  end
50
50
 
51
51
  can :destroy, Comment do |c|
52
- c.post_activity.allow?(subject, 'destroy')
52
+ can? :destroy, c.parent_post
53
53
  end
54
54
 
55
55
  # Activities
56
- can :create, Activity do |a|
57
- a.allow?(subject, 'create')
58
- end
59
-
60
56
  can :read, Activity do |a|
61
57
  a.public? ||
62
58
  subject.present? &&
63
59
  a.audience.include?(subject.actor)
64
60
  end
65
61
 
66
- can :update, Activity do |a|
67
- a.allow?(subject, 'update')
68
- end
69
-
70
- can :destroy, Activity do |a|
71
- a.allow?(subject, 'destroy')
72
- end
73
-
74
62
  # Users
75
63
  can :read, User
76
64