social_stream 0.4.3 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/app/controllers/api_controller.rb +1 -1
- data/app/controllers/contacts_controller.rb +1 -1
- data/app/controllers/conversations_controller.rb +5 -5
- data/app/controllers/groups_controller.rb +1 -0
- data/app/controllers/likes_controller.rb +17 -5
- data/app/controllers/messages_controller.rb +3 -1
- data/app/controllers/profiles_controller.rb +4 -0
- data/app/controllers/representations_controller.rb +12 -1
- data/app/controllers/tags_controller.rb +15 -0
- data/app/controllers/users_controller.rb +3 -0
- data/app/helpers/activities_helper.rb +13 -6
- data/app/models/activity.rb +53 -52
- data/app/models/activity_object.rb +2 -0
- data/app/models/actor.rb +85 -19
- data/app/models/avatar.rb +2 -1
- data/app/models/like.rb +28 -13
- data/app/models/permission.rb +7 -7
- data/app/models/profile.rb +1 -1
- data/app/models/relation/custom.rb +111 -0
- data/app/models/relation/public.rb +42 -0
- data/app/models/relation.rb +1 -89
- data/app/models/sphere.rb +7 -0
- data/app/models/tie.rb +65 -52
- data/app/models/tie_activity.rb +38 -0
- data/app/views/activities/_new.html.erb +4 -4
- data/app/views/activities/_options.html.erb +2 -2
- data/app/views/actors/_actor.html.erb +0 -0
- data/app/views/avatars/index.html.erb +5 -2
- data/app/views/comments/_new.html.erb +2 -2
- data/app/views/contacts/index.html.erb +5 -1
- data/app/views/conversations/edit.html.erb +4 -0
- data/app/views/conversations/index.html.erb +5 -1
- data/app/views/conversations/show.html.erb +4 -0
- data/app/views/frontpage/index.html.erb +4 -0
- data/app/views/groups/_sidebar_index.html.erb +7 -42
- data/app/views/groups/index.html.erb +3 -0
- data/app/views/groups/new.html.erb +3 -0
- data/app/views/groups/show.html.erb +7 -0
- data/app/views/layouts/_account.html.erb +16 -0
- data/app/views/layouts/_footer.html.erb +1 -1
- data/app/views/layouts/_header.erb +7 -22
- data/app/views/layouts/_representation.html.erb +25 -12
- data/app/views/layouts/application.html.erb +6 -3
- data/app/views/layouts/frontpage.html.erb +1 -1
- data/app/views/likes/create.js.erb +1 -1
- data/app/views/likes/destroy.js.erb +1 -1
- data/app/views/messages/new.html.erb +7 -5
- data/app/views/profiles/_profile.html.erb +20 -0
- data/app/views/profiles/edit.html.erb +42 -0
- data/app/views/profiles/show.html.erb +4 -0
- data/app/views/profiles/update.js.erb +5 -0
- data/app/views/subjects/_toolbar_profile_menu_tie_options.html.erb +3 -1
- data/app/views/ties/_new.html.erb +1 -1
- data/app/views/users/index.html.erb +4 -0
- data/app/views/users/show.html.erb +5 -0
- data/config/locales/en.yml +54 -1
- data/config/routes.rb +3 -1
- data/lib/generators/social_stream/install_generator.rb +2 -1
- data/lib/generators/social_stream/templates/migration.rb +23 -27
- data/lib/generators/social_stream/templates/public/images/btn/error.png +0 -0
- data/lib/generators/social_stream/templates/public/images/btn/info.png +0 -0
- data/lib/generators/social_stream/templates/public/images/btn/like.png +0 -0
- data/lib/generators/social_stream/templates/public/images/btn/nolike.png +0 -0
- data/lib/generators/social_stream/templates/public/images/btn/success.png +0 -0
- data/lib/generators/social_stream/templates/public/images/btn/warning.png +0 -0
- data/lib/generators/social_stream/templates/public/javascripts/ajax.paginate.js +12 -19
- data/lib/generators/social_stream/templates/public/javascripts/jquery.validate.js +1 -1
- data/lib/generators/social_stream/templates/public/javascripts/main.js +20 -10
- data/lib/generators/social_stream/templates/public/stylesheets/default/base.css +21 -4
- data/lib/generators/social_stream/templates/public/stylesheets/default/header.css +8 -3
- data/lib/generators/social_stream/templates/relations.yml +7 -13
- data/lib/social_stream/ability.rb +39 -20
- data/lib/social_stream/controllers/helpers.rb +6 -0
- data/lib/social_stream/models/object.rb +8 -4
- data/lib/social_stream/models/subject.rb +6 -0
- data/lib/social_stream/rails.rb +6 -3
- data/lib/social_stream/version.rb +1 -1
- data/lib/tasks/db/populate.rake +11 -1
- data/social_stream.gemspec +7 -8
- data/spec/controllers/comments_controller_spec.rb +6 -2
- data/spec/controllers/posts_controller_spec.rb +93 -5
- data/spec/controllers/profiles_controller_spec.rb +58 -1
- data/spec/controllers/representations_controller_spec.rb +51 -0
- data/spec/controllers/users_controller_spec.rb +28 -0
- data/spec/dummy/config/relations.yml +7 -13
- data/spec/dummy/db/schema.rb +2 -13
- data/spec/factories/tie.rb +1 -1
- data/spec/models/activity_spec.rb +28 -67
- data/spec/models/profile_spec.rb +38 -0
- data/spec/models/tie_activity_spec.rb +88 -31
- data/spec/models/tie_spec.rb +20 -14
- data/spec/support/db.rb +8 -10
- data/spec/support/migrations.rb +24 -0
- metadata +74 -59
data/app/models/permission.rb
CHANGED
@@ -43,10 +43,10 @@
|
|
43
43
|
#
|
44
44
|
# Available functions are:
|
45
45
|
#
|
46
|
-
#
|
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
|
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
|
-
|
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.
|
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.
|
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
|
-
|
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
|
-
|
144
|
+
"#{ pc.last } AND #{ sanitize_sql('permissions.function' => pc.first) }"
|
145
145
|
}.join(" OR ")
|
146
146
|
end
|
147
147
|
end
|
data/app/models/profile.rb
CHANGED
@@ -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
|
data/app/models/relation.rb
CHANGED
@@ -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
|
+
|
data/app/models/tie.rb
CHANGED
@@ -1,16 +1,19 @@
|
|
1
|
-
# A
|
1
|
+
# A {Tie} is a link between two {Actor Actors} with a {Relation}.
|
2
2
|
#
|
3
|
-
# The first {Actor
|
4
|
-
# is the receiver of the {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
|
-
#
|
9
|
-
#
|
10
|
-
#
|
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
|
-
|
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 :
|
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
|
205
|
-
where("permissions.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 =
|
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
|
-
|
233
|
-
|
234
|
-
|
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
|
247
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
data/app/models/tie_activity.rb
CHANGED
@@ -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.
|
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.
|
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.
|
19
|
+
<% if receiver.activity_ties_for(current_subject).count > 1 %>
|
20
20
|
<div id="securities">
|
21
|
-
<%= f.select :_activity_tie_id, receiver.
|
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.
|
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
|
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
|
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.
|
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.
|
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 %>
|