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.
- 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 %>
|