social_stream 0.2.1 → 0.2.2
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/.gitignore +2 -0
- data/Gemfile.lock +1 -1
- data/README.rdoc +4 -4
- data/app/controllers/private_messages_controller.rb +3 -0
- data/app/controllers/users_controller.rb +26 -0
- data/app/models/permission.rb +19 -0
- data/app/models/private_message.rb +6 -0
- data/app/models/profile.rb +3 -0
- data/app/models/tie.rb +28 -2
- data/app/models/user.rb +29 -13
- data/app/views/home/_options.html.erb +4 -1
- data/app/views/home/_right.html.erb +1 -1
- data/app/views/layouts/application.html.erb +7 -4
- data/app/views/private_messages/_form.html.erb +24 -0
- data/app/views/private_messages/_index.html.erb +24 -0
- data/app/views/private_messages/_location.html.erb +3 -0
- data/app/views/private_messages/_messages.html.erb +2 -0
- data/app/views/private_messages/_private_message.html.erb +17 -0
- data/app/views/private_messages/edit.html.erb +6 -0
- data/app/views/private_messages/index.html.erb +1 -0
- data/app/views/private_messages/index.js.erb +1 -0
- data/app/views/private_messages/new.html.erb +14 -0
- data/app/views/private_messages/show.html.erb +21 -0
- data/app/views/users/_contacts.html.erb +2 -0
- data/app/views/users/_profile.html.erb +44 -57
- data/app/views/users/edit.html.erb +164 -0
- data/config/locales/en.yml +5 -4
- data/config/routes.rb +1 -0
- data/lib/generators/social_stream/install_generator.rb +4 -0
- data/lib/generators/social_stream/templates/migration.rb +21 -3
- data/lib/generators/social_stream/templates/public/javascripts/jquery-ui.min.js +401 -0
- data/lib/generators/social_stream/templates/public/stylesheets/edit_user.css +80 -0
- data/lib/generators/social_stream/templates/public/stylesheets/message.css +46 -0
- data/lib/social_stream/populate.rb +26 -0
- data/lib/social_stream/version.rb +1 -1
- data/lib/tasks/db/populate.rake +2 -2
- data/spec/controllers/.groups_controller_spec.rb.swp +0 -0
- data/spec/controllers/.users_controller_spec.rb.swp +0 -0
- data/spec/controllers/frontpage_controller_spec.rb +11 -0
- data/spec/controllers/groups_controller_spec.rb +51 -0
- data/spec/controllers/home_controller_spec.rb +24 -0
- data/spec/controllers/users_controller_spec.rb +48 -0
- data/spec/factories/post.rb +1 -0
- data/spec/factories/user.rb +2 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/support/devise.rb +4 -0
- metadata +29 -7
- data/spec/dummy/app/models/post.rb +0 -2
- data/spec/dummy/app/models/user.rb +0 -2
- data/spec/dummy/app/views/layouts/application.html.erb +0 -14
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
= Social Stream: building social network
|
2
|
-
Social Stream is an engine for Ruby on Rails. It provides
|
3
|
-
|
1
|
+
= Social Stream: core for building social network websites
|
2
|
+
Social Stream is an engine for Ruby on Rails. It provides a robust and flexible core
|
3
|
+
with social networking features and activity streams for building websites.
|
4
4
|
|
5
5
|
== Social networking
|
6
6
|
Social networks are a new paradigm on web application design. Social networking platforms stand
|
@@ -68,7 +68,7 @@ initializer.
|
|
68
68
|
|
69
69
|
= Documentation
|
70
70
|
|
71
|
-
{Social Stream documentation is available at rdoc.info}[http://
|
71
|
+
{Social Stream documentation is available at rdoc.info}[http://rubydoc.info/gems/social_stream/frames]
|
72
72
|
|
73
73
|
= Discussion
|
74
74
|
|
@@ -6,6 +6,32 @@ class UsersController < ApplicationController
|
|
6
6
|
respond_to do |format|
|
7
7
|
format.html # show.html.erb
|
8
8
|
format.xml { render :xml => @user }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def edit
|
13
|
+
@user = User.find_by_permalink!(params[:id])
|
14
|
+
|
15
|
+
respond_to do |format|
|
16
|
+
format.html # edit.html.erb
|
17
|
+
format.xml { render :xml => @user }
|
9
18
|
end
|
10
19
|
end
|
20
|
+
|
21
|
+
def update
|
22
|
+
|
23
|
+
@user = User.find_by_permalink!(params[:id])
|
24
|
+
|
25
|
+
respond_to do |format|
|
26
|
+
if @user.update_attributes(params[:user])
|
27
|
+
#format.html { redirect_to(@user, :notice => 'User was successfully updated.') }
|
28
|
+
format.html { render :action => "edit", :notice => 'User was successfully updated.' }
|
29
|
+
format.xml { head :ok }
|
30
|
+
else
|
31
|
+
format.html { render :action => "edit" }
|
32
|
+
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
11
37
|
end
|
data/app/models/permission.rb
CHANGED
@@ -1,7 +1,26 @@
|
|
1
|
+
# SocialStream provides a sophisticated and powerful system of permissions based on the relations
|
2
|
+
# and ties of the social network.
|
3
|
+
#
|
4
|
+
# Permissions are composed by action, objective and parameterized. Action and objective are classical
|
5
|
+
# in content management systems, e.g. "create" "activity", "update" "tie", "read" "post"
|
6
|
+
#
|
7
|
+
# parameterized is a novel feature. It supports applying the permission to certain set of ties.
|
8
|
+
# This set of ties changes with the formation of ties in your website.
|
9
|
+
#
|
10
|
+
# Permissions is assigned to relations, and through relations, to ties.
|
11
|
+
# When a sender establishes a tie with a receiver, she grants to the receiver the permissions assigned
|
12
|
+
# to relation of the tie she has just established. For example, when Alice establishes a "friend" tie
|
13
|
+
# to Bob, she is granting him the permissions associated with "friend" relation.
|
14
|
+
#
|
15
|
+
# One of this permissions can be "read" "activity" "inverse_group_set". This way, Bob will have access
|
16
|
+
# to read the activities attached to ties inside the "inverse_group_set", which are the ties from all
|
17
|
+
# the "friends" of Alice to Alice herself.
|
18
|
+
#
|
1
19
|
class Permission < ActiveRecord::Base
|
2
20
|
has_many :relation_permissions, :dependent => :destroy
|
3
21
|
has_many :relations, :through => :relation_permissions
|
4
22
|
|
23
|
+
# The SQL and ARel conditions for permission queries
|
5
24
|
ParameterConditions = {
|
6
25
|
:table => {
|
7
26
|
'tie' =>
|
data/app/models/tie.rb
CHANGED
@@ -121,8 +121,34 @@ class Tie < ActiveRecord::Base
|
|
121
121
|
Tie.inverse(self).first
|
122
122
|
end
|
123
123
|
|
124
|
-
# Access Control
|
125
|
-
|
124
|
+
# = Access Control
|
125
|
+
#
|
126
|
+
# Access control enforcement in ties come from the permissions assigned to other ties through relations.
|
127
|
+
# The access_set is the set of ties that grant some permission on a particular tie.
|
128
|
+
#
|
129
|
+
# Enforcing access control on activities and ties are a matter of finding its access set.
|
130
|
+
# There are two approaches for this, checking the permissions on particular tie or finding all the ties
|
131
|
+
# granted some permission.
|
132
|
+
#
|
133
|
+
# == Particular tie
|
134
|
+
# ------------------ ------------------
|
135
|
+
# | particular tie |--------| access_set |
|
136
|
+
# | t | | ties |
|
137
|
+
# ------------------ ------------------
|
138
|
+
#
|
139
|
+
# Because t is given, the scopes are applied to the ties table
|
140
|
+
# We get the set of ties that allow permission on t
|
141
|
+
#
|
142
|
+
# == Finding ties
|
143
|
+
# ------------------ join ------------------
|
144
|
+
# | finding ties |--------| access_set |
|
145
|
+
# | ties | | ties_as |
|
146
|
+
# ------------------ ------------------
|
147
|
+
#
|
148
|
+
# Because we want to find ties, an additional join table (ties_as) is needed for applying access set conditions
|
149
|
+
# We get the set of ties that are allowed to certain condition
|
150
|
+
#
|
151
|
+
|
126
152
|
scope :with_permissions, lambda { |action, object|
|
127
153
|
joins(:relation => :permissions).
|
128
154
|
where('permissions.action' => action).
|
data/app/models/user.rb
CHANGED
@@ -2,24 +2,38 @@ require 'devise/orm/active_record'
|
|
2
2
|
|
3
3
|
class User < ActiveRecord::Base
|
4
4
|
devise *SocialStream.devise_modules
|
5
|
-
|
5
|
+
has_one :profile
|
6
|
+
accepts_nested_attributes_for :profile
|
7
|
+
|
6
8
|
# Setup accessible (or protected) attributes for your model
|
7
|
-
attr_accessible :name, :email, :password, :password_confirmation, :remember_me
|
8
|
-
|
9
|
+
attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :profile_attributes, :birthday
|
10
|
+
|
9
11
|
validates_presence_of :email
|
12
|
+
|
10
13
|
validates_format_of :email, :with => Devise.email_regexp, :allow_blank => true
|
11
14
|
# TODO: uniqueness of email, which is in actor
|
12
|
-
|
15
|
+
|
13
16
|
with_options :if => :password_required? do |v|
|
14
17
|
v.validates_presence_of :password
|
15
18
|
v.validates_confirmation_of :password
|
16
19
|
v.validates_length_of :password, :within => Devise.password_length, :allow_blank => true
|
17
20
|
end
|
18
|
-
|
21
|
+
|
19
22
|
def recent_groups
|
20
23
|
receiver_subjects(:group, :relations => 'follower') & Tie.recent
|
21
24
|
end
|
22
25
|
|
26
|
+
|
27
|
+
|
28
|
+
def age
|
29
|
+
return nil if self.birthday.blank?
|
30
|
+
now = Time.now.utc.to_date
|
31
|
+
now.year - self.birthday.year - (self.birthday.to_date.change(:year => now.year) > now ? 1 : 0)
|
32
|
+
end
|
33
|
+
|
34
|
+
after_create :create_profile
|
35
|
+
|
36
|
+
|
23
37
|
def friends
|
24
38
|
receiver_subjects(:user, :relations => 'friend')
|
25
39
|
end
|
@@ -30,7 +44,7 @@ class User < ActiveRecord::Base
|
|
30
44
|
def password_required?
|
31
45
|
!persisted? || !password.nil? || !password_confirmation.nil?
|
32
46
|
end
|
33
|
-
|
47
|
+
|
34
48
|
class << self
|
35
49
|
%w( email permalink name ).each do |a|
|
36
50
|
eval <<-EOS
|
@@ -42,7 +56,7 @@ class User < ActiveRecord::Base
|
|
42
56
|
end # end
|
43
57
|
EOS
|
44
58
|
end
|
45
|
-
|
59
|
+
|
46
60
|
# Overwrite devise default find method to support login with email,
|
47
61
|
# presence ID and login
|
48
62
|
def find_for_authentication(conditions)
|
@@ -56,7 +70,7 @@ class User < ActiveRecord::Base
|
|
56
70
|
super
|
57
71
|
end
|
58
72
|
end
|
59
|
-
|
73
|
+
|
60
74
|
def find_or_initialize_with_error_by(attribute, value, error=:invalid)
|
61
75
|
if attribute == :email
|
62
76
|
find_or_initialize_with_error_by_email(value, error)
|
@@ -64,26 +78,28 @@ class User < ActiveRecord::Base
|
|
64
78
|
super
|
65
79
|
end
|
66
80
|
end
|
67
|
-
|
81
|
+
|
68
82
|
# Overwrite devise default method to support finding with actor.email
|
69
83
|
def find_or_initialize_with_error_by_email(value, error)
|
70
84
|
if value.present?
|
71
85
|
record = find_by_email(value)
|
72
86
|
end
|
73
|
-
|
87
|
+
|
74
88
|
unless record
|
75
89
|
record = new
|
76
|
-
|
90
|
+
|
77
91
|
if value.present?
|
78
92
|
record.email = value
|
79
93
|
else
|
80
94
|
error = :blank
|
81
95
|
end
|
82
|
-
|
96
|
+
|
83
97
|
record.errors.add(:email, error)
|
84
98
|
end
|
85
|
-
|
99
|
+
|
86
100
|
record
|
87
101
|
end
|
88
102
|
end
|
103
|
+
|
104
|
+
|
89
105
|
end
|
@@ -1,5 +1,8 @@
|
|
1
1
|
<ul class="menu noaccordion">
|
2
2
|
<li>
|
3
|
-
<%= link_to( image_tag("btn/btn_inbox.png", :class => "menu_icon")+t('inbox.one'),
|
3
|
+
<%= link_to( image_tag("btn/btn_inbox.png", :class => "menu_icon")+t('inbox.one'), private_messages_path, :remote => true) %>
|
4
|
+
</li>
|
5
|
+
<li>
|
6
|
+
<%= link_to( image_tag("btn/btn_group.png", :class => "menu_icon")+t('group.new'), "#", :remote => true) %>
|
4
7
|
</li>
|
5
8
|
</ul>
|
@@ -18,11 +18,14 @@
|
|
18
18
|
<%= stylesheet_link_tag "carousel", :media => "screen, projection" %>
|
19
19
|
<%= stylesheet_link_tag "smoothness/jquery-ui-1.8.4.custom", :media => "screen, projection" %>
|
20
20
|
<%= stylesheet_link_tag "ui.dropdownchecklist", :media => "screen, projection" %>
|
21
|
+
<!-- datepicker css -->
|
22
|
+
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>
|
23
|
+
<%= stylesheet_link_tag "edit_user", :media => "screen, projection" %>
|
21
24
|
|
22
25
|
|
23
26
|
<%= javascript_include_tag :defaults %>
|
24
27
|
|
25
|
-
<%= javascript_include_tag 'jquery', 'jquery-ui
|
28
|
+
<%= javascript_include_tag 'jquery', 'jquery-ui.min', 'jquery.livequery',
|
26
29
|
'jquery.boxy', 'menu','ui.dropdownchecklist' %>
|
27
30
|
|
28
31
|
|
@@ -47,11 +50,11 @@
|
|
47
50
|
</div>
|
48
51
|
<div id="middle">
|
49
52
|
<div id="middleContent">
|
50
|
-
<div class="
|
53
|
+
<div class="space_profile">
|
51
54
|
</div>
|
52
|
-
<div class="
|
55
|
+
<div class="space_profile">
|
53
56
|
</div>
|
54
|
-
<div class="
|
57
|
+
<div class="space_profile">
|
55
58
|
</div>
|
56
59
|
<%= yield :middle %>
|
57
60
|
</div>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<%= form_for(@private_message) do |f| %>
|
2
|
+
<% if @private_message.errors.any? %>
|
3
|
+
<div id="error_explanation">
|
4
|
+
<h2><%= pluralize(@private_message.errors.count, "error") %> prohibited this private_message from being saved:</h2>
|
5
|
+
|
6
|
+
<ul>
|
7
|
+
<% @private_message.errors.full_messages.each do |msg| %>
|
8
|
+
<li><%= msg %></li>
|
9
|
+
<% end %>
|
10
|
+
</ul>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<%= f.hidden_field :sender_id %>
|
15
|
+
<%= f.hidden_field :receiver_id %>
|
16
|
+
|
17
|
+
<div class="field">
|
18
|
+
<%= f.label :text %><br />
|
19
|
+
<%= f.text_area :text %>
|
20
|
+
</div>
|
21
|
+
<div class="actions">
|
22
|
+
<%= f.submit %>
|
23
|
+
</div>
|
24
|
+
<% end %>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<% content_for :middle do %>
|
2
|
+
<%= render :partial => 'home/middle' %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% content_for :right do %>
|
6
|
+
<%= render :partial => "home/right" %>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<%= render :partial => 'location' %>
|
10
|
+
|
11
|
+
<br class="clearfloat" />
|
12
|
+
<div class="space_center">
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<div id="new_message" ><%= link_to 'New Message', new_private_message_path %></div>
|
16
|
+
<div class="space_center">
|
17
|
+
</div>
|
18
|
+
<div class="space_center">
|
19
|
+
</div>
|
20
|
+
|
21
|
+
|
22
|
+
<div id="messages">
|
23
|
+
<%= render :partial => 'messages' %>
|
24
|
+
</div>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<%= div_for (private_message) do %>
|
2
|
+
<div class="actor_logo">
|
3
|
+
<%= link_to image_tag(private_message.text,
|
4
|
+
:alt => private_message.text),
|
5
|
+
private_message %>
|
6
|
+
</div>
|
7
|
+
<div class="activity_content_message">
|
8
|
+
<div class="actor_name_message">
|
9
|
+
<%= link_to(private_message.text, private_message) %>
|
10
|
+
</div>
|
11
|
+
<div class="option_msg">
|
12
|
+
<div class="edit_message"><%= link_to ( image_tag('btn/btn_edit.png', :class=>"btn_config"), edit_private_message_path(private_message)) %></div>
|
13
|
+
<div class="detele_message"><%= link_to ( image_tag('btn/btn_delete.png', :class=>"btn_config"), private_message, :confirm => 'Are you sure?', :method => :delete) %></div>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render :partial => 'index' %>
|
@@ -0,0 +1 @@
|
|
1
|
+
$("#content").html("<%=escape_javascript(render :partial => 'index') %>");
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<% content_for :middle do %>
|
2
|
+
<%= render :partial => 'home/middle' %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% content_for :right do %>
|
6
|
+
<%= render :partial => "home/right" %>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
|
10
|
+
<h1>New private_message</h1>
|
11
|
+
|
12
|
+
<%= render 'form' %>
|
13
|
+
|
14
|
+
<%= link_to 'Back', private_messages_path %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
<p id="notice"><%= notice %></p>
|
3
|
+
|
4
|
+
<p>
|
5
|
+
<b>Sender:</b>
|
6
|
+
<%= @private_message.sender %>
|
7
|
+
</p>
|
8
|
+
|
9
|
+
<p>
|
10
|
+
<b>Receiver:</b>
|
11
|
+
<%= @private_message.receiver %>
|
12
|
+
</p>
|
13
|
+
|
14
|
+
<p>
|
15
|
+
<b>Text:</b>
|
16
|
+
<%= @private_message.text %>
|
17
|
+
</p>
|
18
|
+
|
19
|
+
|
20
|
+
<%= link_to 'Edit', edit_private_message_path(@private_message) %> |
|
21
|
+
<%= link_to 'Back', private_messages_path %>
|