social_stream-base 0.6.3 → 0.6.5
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/assets/stylesheets/base.css +1 -0
- data/app/assets/stylesheets/contacts.css +2 -1
- data/app/assets/stylesheets/fcbkComplete.css +1 -1
- data/app/assets/stylesheets/header.css +2 -2
- data/app/assets/stylesheets/messages.css +3 -3
- data/app/assets/stylesheets/{spheres.css → relation_customs.css} +0 -0
- data/app/controllers/contacts_controller.rb +9 -4
- data/app/controllers/messages_controller.rb +69 -68
- data/app/controllers/relation/customs_controller.rb +1 -11
- data/app/helpers/activities_helper.rb +1 -2
- data/app/helpers/notifications_helper.rb +3 -2
- data/app/helpers/permissions_helper.rb +5 -5
- data/app/helpers/subjects_helper.rb +9 -0
- data/app/helpers/toolbar_helper.rb +10 -89
- data/app/models/activity.rb +39 -15
- data/app/models/actor.rb +30 -71
- data/app/models/contact.rb +15 -0
- data/app/models/group.rb +1 -3
- data/app/models/permission.rb +9 -72
- data/app/models/profile.rb +7 -2
- data/app/models/relation/custom.rb +6 -33
- data/app/models/relation.rb +15 -39
- data/app/models/user.rb +5 -1
- data/app/views/activities/_new.html.erb +5 -2
- data/app/views/activities/_options.html.erb +2 -2
- data/app/views/activities/_walls.html.erb +1 -1
- data/app/views/contacts/_contact.html.erb +3 -3
- data/app/views/contacts/_form.html.erb +14 -20
- data/app/views/contacts/_index.html.erb +1 -1
- data/app/views/contacts/_suggestions.html.erb +1 -13
- data/app/views/contacts/destroy.js.erb +6 -0
- data/app/views/contacts/edit.html.erb +1 -1
- data/app/views/conversations/_conversation.html.erb +1 -1
- data/app/views/groups/_group.html.erb +1 -1
- data/app/views/groups/_index.html.erb +1 -1
- data/app/views/groups/show.html.erb +1 -1
- data/app/views/invitation_mailer/send_invitation.html.erb +17 -6
- data/app/views/invitation_mailer/send_invitation.text.erb +7 -2
- data/app/views/layouts/_representation.html.erb +10 -6
- data/app/views/layouts/_settings.html.erb +1 -1
- data/app/views/messages/_message.html.erb +1 -1
- data/app/views/messages/new.html.erb +1 -1
- data/app/views/notifications/_notification.html.erb +7 -3
- data/app/views/objects/_new.html.erb +0 -6
- data/app/views/profiles/edit.html.erb +5 -9
- data/app/views/relation/customs/_form.html.erb +2 -2
- data/app/views/{spheres → relation/customs}/_jquery.erb +0 -58
- data/app/views/relation/customs/_list.html.erb +9 -26
- data/app/views/relation/customs/create.js.erb +2 -3
- data/app/views/relation/customs/index.html.erb +67 -0
- data/app/views/users/_index.html.erb +1 -1
- data/app/views/users/show.html.erb +1 -1
- data/config/locales/en.yml +16 -41
- data/config/routes.rb +1 -6
- data/db/migrate/20110705103202_empty_ties_count.rb +4 -0
- data/db/migrate/20110712090343_remove_spheres.rb +30 -0
- data/db/migrate/20110712142140_remove_permission_function.rb +26 -0
- data/lib/generators/social_stream/base/install_generator.rb +4 -0
- data/lib/generators/social_stream/base/templates/mailboxer_custom.rb +13 -0
- data/lib/generators/social_stream/base/templates/navigation.rb +4 -0
- data/lib/generators/social_stream/base/templates/relations.yml +14 -20
- data/lib/social_stream/ability.rb +1 -2
- data/lib/social_stream/base/version.rb +1 -1
- data/lib/social_stream/migration_finder.rb +19 -0
- data/lib/social_stream/toolbar_config.rb +113 -0
- data/lib/social_stream-base.rb +1 -0
- data/lib/tasks/db/populate.rake +1 -1
- data/social_stream-base.gemspec +4 -2
- data/spec/controllers/contacts_controller_spec.rb +1 -1
- data/spec/controllers/permissions_controller_spec.rb +1 -2
- data/spec/controllers/posts_controller_spec.rb +2 -2
- data/spec/controllers/relation_customs_controller_spec.rb +69 -62
- data/spec/dummy/config/database.yml +7 -0
- data/spec/dummy/config/relations.yml +14 -20
- data/spec/factories/relation_custom.rb +1 -1
- data/spec/factories/tie.rb +4 -0
- data/spec/models/activity_spec.rb +11 -2
- data/spec/models/user_spec.rb +68 -9
- data/spec/spec_helper.rb +0 -3
- data/spec/support/db.rb +9 -0
- data/spec/support/migrations.rb +3 -12
- metadata +19 -25
- data/app/controllers/spheres_controller.rb +0 -12
- data/app/models/sphere.rb +0 -9
- data/app/views/relation/customs/_index.html.erb +0 -28
- data/app/views/relation/customs/index.js.erb +0 -2
- data/app/views/spheres/_form.html.erb +0 -28
- data/app/views/spheres/_list.html.erb +0 -19
- data/app/views/spheres/create.js.erb +0 -20
- data/app/views/spheres/index.html.erb +0 -74
- data/spec/controllers/spheres_controller_spec.rb +0 -116
- data/spec/factories/sphere.rb +0 -5
- data/spec/models/relation_custom_spec.rb +0 -14
@@ -0,0 +1,19 @@
|
|
1
|
+
module SocialStream
|
2
|
+
# Searches for migrations in a gem and requires them.
|
3
|
+
# Example:
|
4
|
+
#
|
5
|
+
# MigrationFinder.new 'acts-as-taggable-on',
|
6
|
+
# ["generators", "acts_as_taggable_on", "migration", "templates", "active_record", "migration"]
|
7
|
+
# ActsAsTaggableOnMigration.up
|
8
|
+
class MigrationFinder
|
9
|
+
def initialize gem, path
|
10
|
+
finder = Gem::GemPathSearcher.new
|
11
|
+
taggable_spec = finder.find(gem)
|
12
|
+
taggable_migration = finder.matching_files(taggable_spec,
|
13
|
+
File.join(*path)).first
|
14
|
+
|
15
|
+
require taggable_migration
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module SocialStream
|
2
|
+
module ToolbarConfig
|
3
|
+
#Prints the default home toolbar menu
|
4
|
+
def default_home_toolbar_menu
|
5
|
+
items = Array.new
|
6
|
+
#Notifications
|
7
|
+
items << {:key => :notifications,
|
8
|
+
:name => image_tag("btn/btn_notification.png")+t('notification.other')+' ('+ current_subject.mailbox.notifications.not_trashed.unread.count.to_s+')',
|
9
|
+
:url => notifications_path,
|
10
|
+
:options => {:link => {:id => "notifications_menu"}}}
|
11
|
+
|
12
|
+
#Messages
|
13
|
+
items << {:key => :messages,
|
14
|
+
:name => image_tag("btn/new.png")+t('message.other')+' (' + current_subject.mailbox.inbox(:unread => true).count.to_s + ')',
|
15
|
+
:url => "#",
|
16
|
+
:options => {:link => {:id => "messages_menu"}},
|
17
|
+
:items => [
|
18
|
+
{:key => :message_new, :name => image_tag("btn/message_new.png")+ t('message.new'), :url => new_message_path},
|
19
|
+
{:key => :message_inbox, :name => image_tag("btn/message_inbox.png")+t('message.inbox')+' (' + current_subject.mailbox.inbox(:unread => true).count.to_s + ')',
|
20
|
+
:url => conversations_path, :options => {:link =>{:remote=> true}}},
|
21
|
+
{:key => :message_sentbox, :name => image_tag("btn/message_sentbox.png")+t('message.sentbox'), :url => conversations_path(:box => :sentbox), :remote=> true},
|
22
|
+
{:key => :message_trash, :name => image_tag("btn/message_trash.png")+t('message.trash'), :url => conversations_path(:box => :trash)}
|
23
|
+
]}
|
24
|
+
|
25
|
+
#Documents if present
|
26
|
+
if SocialStream.activity_forms.include? :document
|
27
|
+
items << {:key => :resources,
|
28
|
+
:name => image_tag("btn/btn_resource.png",:class =>"menu_icon")+t('resource.mine'),
|
29
|
+
:url => "#",
|
30
|
+
:options => {:link => {:id => "resources_menu"}},
|
31
|
+
:items => [
|
32
|
+
{:key => :resources_documents,:name => image_tag("btn/btn_documents.png")+t('document.title'),:url => documents_path},
|
33
|
+
{:key => :resources_pictures,:name => image_tag("btn/btn_gallery.png")+t('picture.title'),:url => pictures_path},
|
34
|
+
{:key => :resources_videos,:name => image_tag("btn/btn_video.png")+t('video.title'),:url => videos_path},
|
35
|
+
{:key => :resources_audios,:name => image_tag("btn/btn_audio.png")+t('audio.title'),:url => audios_path}
|
36
|
+
]}
|
37
|
+
end
|
38
|
+
|
39
|
+
#Contacts
|
40
|
+
relation_items = [{:key => :invitations, :name => image_tag("btn/btn_invitation.png")+t('invitation.other'), :url => new_invitation_path}]
|
41
|
+
current_subject.relation_customs.sort.each do |r|
|
42
|
+
relation_items << {:key => r.name + "_menu",
|
43
|
+
:name => image_tag("btn/btn_friend.png") + r.name,
|
44
|
+
:url => contacts_path(:relation => r.id)}
|
45
|
+
end
|
46
|
+
items << {:key => :contacts,
|
47
|
+
:name => image_tag("btn/btn_friend.png")+t('contact.other'),
|
48
|
+
:url => "#",
|
49
|
+
:options => {:link => {:id => "contacts_menu"}},
|
50
|
+
:items => relation_items}
|
51
|
+
|
52
|
+
#Subjects
|
53
|
+
items << {:key => :groups,
|
54
|
+
:name => image_tag("btn/btn_group.png")+t('group.other'),
|
55
|
+
:url => "#",
|
56
|
+
:options => {:link => {:id => "groups_menu"}},
|
57
|
+
:items => [{:key => :new_group ,:name => image_tag("btn/btn_group.png")+t('group.new.action'),:url => new_group_path('group' => { '_founder' => current_subject.slug })}]
|
58
|
+
}
|
59
|
+
|
60
|
+
render_items items
|
61
|
+
end
|
62
|
+
|
63
|
+
#Prints the default profile toolbar menu
|
64
|
+
def default_profile_toolbar_menu(subject = current_subject)
|
65
|
+
items = Array.new
|
66
|
+
#Information button
|
67
|
+
items << {:key => :subject_info,
|
68
|
+
:name => image_tag("btn/btn_edit.png")+t('menu.information'),
|
69
|
+
:url => [subject, :profile]
|
70
|
+
}
|
71
|
+
|
72
|
+
if subject!=current_subject
|
73
|
+
#Like button
|
74
|
+
items << {:key => :like_button,
|
75
|
+
:name => link_like_params(subject)[0],
|
76
|
+
:url => link_like_params(subject)[1],
|
77
|
+
:options => {:link => link_like_params(subject)[2]}}
|
78
|
+
|
79
|
+
if user_signed_in?
|
80
|
+
#Relation button
|
81
|
+
items << {:key => :subject_relation,
|
82
|
+
:name => image_tag("btn/btn_friend.png") + contact_status(subject),
|
83
|
+
:url => edit_contact_path(current_subject.contact_to!(subject))
|
84
|
+
}
|
85
|
+
#Send message button
|
86
|
+
items << {:key => :send_message,
|
87
|
+
:name => image_tag("btn/btn_send.png")+t('message.send'),
|
88
|
+
:url => new_message_path(:receiver => subject.slug)
|
89
|
+
}
|
90
|
+
end
|
91
|
+
end
|
92
|
+
#Documents if present
|
93
|
+
if SocialStream.activity_forms.include? :document
|
94
|
+
if subject == current_subject
|
95
|
+
resources_label = t('resource.mine')
|
96
|
+
else
|
97
|
+
resources_label = t('resource.title')
|
98
|
+
end
|
99
|
+
items << {:key => :resources,
|
100
|
+
:name => image_tag("btn/btn_resource.png",:class =>"menu_icon")+resources_label,
|
101
|
+
:url => "#",
|
102
|
+
:options => {:link => {:id => "resources_menu"}},
|
103
|
+
:items => [
|
104
|
+
{:key => :resources_documents,:name => image_tag("btn/btn_documents.png")+t('document.title'),:url => documents_path},
|
105
|
+
{:key => :resources_pictures,:name => image_tag("btn/btn_gallery.png")+t('picture.title'),:url => pictures_path},
|
106
|
+
{:key => :resources_videos,:name => image_tag("btn/btn_video.png")+t('video.title'),:url => videos_path},
|
107
|
+
{:key => :resources_audios,:name => image_tag("btn/btn_audio.png")+t('audio.title'),:url => audios_path}
|
108
|
+
]}
|
109
|
+
end
|
110
|
+
render_items items
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
data/lib/social_stream-base.rb
CHANGED
@@ -40,6 +40,7 @@ module SocialStream
|
|
40
40
|
autoload :Populate, 'social_stream/populate'
|
41
41
|
autoload :Relations, 'social_stream/relations'
|
42
42
|
autoload :TestHelpers, 'social_stream/test_helpers'
|
43
|
+
autoload :ToolbarConfig, 'social_stream/toolbar_config'
|
43
44
|
|
44
45
|
module Controllers
|
45
46
|
autoload :Helpers, 'social_stream/controllers/helpers'
|
data/lib/tasks/db/populate.rake
CHANGED
@@ -118,7 +118,7 @@ namespace :db do
|
|
118
118
|
|
119
119
|
p = Post.create :text =>
|
120
120
|
"This post should be for #{ t.relation.name } of #{ t.sender.name }.\n#{ Forgery::LoremIpsum.paragraph(:random => true) }",
|
121
|
-
:created_at => Time.at(rand(updated)),
|
121
|
+
:created_at => Time.at(rand(updated.to_i)),
|
122
122
|
:updated_at => updated,
|
123
123
|
:_contact_id => t.contact_id,
|
124
124
|
:_relation_ids => Array(t.relation_id)
|
data/social_stream-base.gemspec
CHANGED
@@ -35,7 +35,7 @@ Gem::Specification.new do |s|
|
|
35
35
|
# OAuth provider
|
36
36
|
s.add_runtime_dependency('oauth-plugin','~> 0.4.0.pre1')
|
37
37
|
# Messages
|
38
|
-
s.add_runtime_dependency('mailboxer','~> 0.2
|
38
|
+
s.add_runtime_dependency('mailboxer','~> 0.3.2')
|
39
39
|
# Avatar manipulation
|
40
40
|
s.add_runtime_dependency('rmagick','~> 2.13.1')
|
41
41
|
# Tagging
|
@@ -56,7 +56,9 @@ Gem::Specification.new do |s|
|
|
56
56
|
s.add_development_dependency('sqlite3-ruby')
|
57
57
|
# Debugging
|
58
58
|
if RUBY_VERSION < '1.9'
|
59
|
-
s.add_development_dependency('ruby-debug'
|
59
|
+
s.add_development_dependency('ruby-debug')
|
60
|
+
else
|
61
|
+
s.add_development_dependency('ruby-debug19')
|
60
62
|
end
|
61
63
|
# Specs
|
62
64
|
s.add_development_dependency('rspec-rails', '~> 2.6.1')
|
@@ -63,7 +63,7 @@ describe ContactsController do
|
|
63
63
|
contact = @user.contact_to!(group)
|
64
64
|
# Initialize inverse contact
|
65
65
|
contact.inverse!
|
66
|
-
relations = [ @user.relation_custom('friend'), @user.relation_custom('
|
66
|
+
relations = [ @user.relation_custom('friend'), @user.relation_custom('colleague') ]
|
67
67
|
|
68
68
|
|
69
69
|
put :update, :id => contact.id,
|
@@ -14,8 +14,7 @@ describe PermissionsController do
|
|
14
14
|
|
15
15
|
context "with an existing relation" do
|
16
16
|
before do
|
17
|
-
@
|
18
|
-
@relation = Factory(:relation_custom, :sphere_id => @sphere.id)
|
17
|
+
@relation = Factory(:relation_custom, :actor_id => @user.actor_id)
|
19
18
|
end
|
20
19
|
|
21
20
|
it "should render index" do
|
@@ -76,10 +76,10 @@ describe PostsController do
|
|
76
76
|
@group = Factory(:member, :contact => Factory(:group_contact, :receiver => @user.actor)).sender_subject
|
77
77
|
end
|
78
78
|
|
79
|
-
describe "with
|
79
|
+
describe "with member relation" do
|
80
80
|
before do
|
81
81
|
contact = @user.contact_to!(@group)
|
82
|
-
relation = @group.
|
82
|
+
relation = @group.relation_custom('member')
|
83
83
|
|
84
84
|
model_assigned_to contact, relation
|
85
85
|
@current_model = Factory(:post, :_contact_id => contact.id, :_relation_ids => Array(relation.id))
|
@@ -1,103 +1,112 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
2
|
|
3
3
|
describe Relation::CustomsController do
|
4
|
-
include SocialStream::TestHelpers::Controllers
|
5
|
-
|
6
4
|
render_views
|
7
5
|
|
8
|
-
describe "when
|
9
|
-
|
10
|
-
|
6
|
+
describe "when Anonymous" do
|
7
|
+
context "faking a new relation" do
|
8
|
+
it "should not create" do
|
9
|
+
post :create, :custom => Factory.attributes_for(:relation_custom)
|
11
10
|
|
12
|
-
|
11
|
+
response.should redirect_to(:new_user_session)
|
12
|
+
end
|
13
13
|
end
|
14
14
|
|
15
|
-
context "
|
15
|
+
context "an existing relation" do
|
16
16
|
before do
|
17
|
-
@
|
17
|
+
@relation = Factory(:relation_custom)
|
18
18
|
end
|
19
19
|
|
20
|
-
it "should
|
21
|
-
|
20
|
+
it "should not update" do
|
21
|
+
put :update, :id => @relation.to_param, :custom => { :name => 'Testing' }
|
22
22
|
|
23
|
-
|
23
|
+
assigns(:custom).should be_blank
|
24
|
+
response.should redirect_to(:new_user_session)
|
24
25
|
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
27
|
+
it "should not destroy" do
|
28
|
+
count = Relation.count
|
29
|
+
begin
|
30
|
+
delete :destroy, :id => @relation.to_param
|
31
|
+
rescue CanCan::AccessDenied
|
32
|
+
end
|
29
33
|
|
30
|
-
|
34
|
+
relation = assigns(:custom)
|
31
35
|
|
32
|
-
|
36
|
+
Relation.count.should eq(count)
|
37
|
+
end
|
33
38
|
|
34
|
-
|
35
|
-
|
36
|
-
response.should be_success
|
37
|
-
end
|
39
|
+
end
|
40
|
+
end
|
38
41
|
|
39
|
-
end
|
40
42
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
describe "when authenticated" do
|
44
|
+
before do
|
45
|
+
@user = Factory(:user)
|
46
|
+
|
47
|
+
sign_in @user
|
48
|
+
end
|
46
49
|
|
47
|
-
|
48
|
-
|
50
|
+
it "should render index" do
|
51
|
+
get :index
|
49
52
|
|
50
|
-
|
53
|
+
response.should be_success
|
54
|
+
end
|
51
55
|
|
52
|
-
|
56
|
+
context "a new own relation" do
|
57
|
+
it "should be created" do
|
58
|
+
count = Relation::Custom.count
|
53
59
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
60
|
+
post :create, :custom => { :name => "Test create", :actor_id => @user.actor_id }, :format => 'js'
|
61
|
+
|
62
|
+
relation = assigns(:custom)
|
58
63
|
|
59
|
-
|
60
|
-
|
64
|
+
Relation::Custom.count.should eq(count + 1)
|
65
|
+
relation.should be_valid
|
66
|
+
response.should be_success
|
67
|
+
end
|
68
|
+
end
|
61
69
|
|
62
|
-
|
70
|
+
context "a new fake relation" do
|
71
|
+
it "should not be created" do
|
72
|
+
count = Relation.count
|
73
|
+
begin
|
74
|
+
post :create, :custom => Factory.attributes_for(:relation_custom)
|
63
75
|
|
64
|
-
|
76
|
+
assert false
|
77
|
+
rescue CanCan::AccessDenied
|
78
|
+
assigns(:custom).should be_new_record
|
65
79
|
|
66
|
-
Relation
|
80
|
+
Relation.count.should eq(count)
|
67
81
|
end
|
68
82
|
end
|
69
|
-
|
70
83
|
end
|
71
84
|
|
72
|
-
context "
|
85
|
+
context "a existing own relation" do
|
73
86
|
before do
|
74
|
-
@
|
87
|
+
@relation = Factory(:relation_custom, :actor => @user.actor)
|
75
88
|
end
|
76
89
|
|
77
|
-
it "should
|
78
|
-
|
79
|
-
get :index, :sphere_id => @sphere.id, :format => "js"
|
90
|
+
it "should allow updating" do
|
91
|
+
attrs = { :name => "Updating own" }
|
80
92
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
93
|
+
put :update, :id => @relation.to_param, :relation_custom => attrs, :format => 'js'
|
94
|
+
|
95
|
+
relation = assigns(:custom)
|
96
|
+
|
97
|
+
# relation.should_receive(:update_attributes).with(attrs)
|
98
|
+
relation.should be_valid
|
99
|
+
response.should be_success
|
86
100
|
end
|
87
101
|
|
88
|
-
|
89
|
-
|
90
|
-
count = Relation::Custom.count
|
102
|
+
it "should allow destroying" do
|
103
|
+
pending "Delete relations"
|
91
104
|
|
92
|
-
|
93
|
-
post :create, :relation_custom => { :name => "Test create", :sphere_id => @sphere.id }, :format => 'js'
|
105
|
+
count = Relation::Custom.count
|
94
106
|
|
95
|
-
|
96
|
-
rescue CanCan::AccessDenied
|
107
|
+
delete :destroy, :id => @relation.to_param, :format => :js
|
97
108
|
|
98
|
-
|
99
|
-
end
|
100
|
-
end
|
109
|
+
Relation::Custom.count.should eq(count - 1)
|
101
110
|
end
|
102
111
|
end
|
103
112
|
|
@@ -126,8 +135,6 @@ describe Relation::CustomsController do
|
|
126
135
|
end
|
127
136
|
end
|
128
137
|
end
|
129
|
-
|
130
|
-
|
131
138
|
end
|
132
139
|
end
|
133
140
|
|
@@ -11,35 +11,29 @@ user:
|
|
11
11
|
friend:
|
12
12
|
name: friend
|
13
13
|
permissions:
|
14
|
-
- [ follow ]
|
15
|
-
- [ create, activity
|
16
|
-
- [ read, activity
|
17
|
-
sphere: personal
|
14
|
+
- [ follow ]
|
15
|
+
- [ create, activity ]
|
16
|
+
- [ read, activity ]
|
18
17
|
acquaintance:
|
19
18
|
name: acquaintance
|
20
|
-
parent: friend # friend relation is stronger than acquaintance
|
21
19
|
permissions:
|
22
|
-
- [ read, activity
|
23
|
-
|
24
|
-
|
25
|
-
name: partner
|
20
|
+
- [ read, activity ]
|
21
|
+
colleague:
|
22
|
+
name: colleague
|
26
23
|
permissions:
|
27
|
-
- [
|
28
|
-
|
24
|
+
- [ follow ]
|
25
|
+
- [ create, activity ]
|
26
|
+
- [ read, activity ]
|
29
27
|
|
30
28
|
group:
|
31
29
|
member:
|
32
30
|
name: member
|
33
31
|
permissions:
|
34
|
-
- [ represent ]
|
35
|
-
- [ create, activity
|
36
|
-
- [ read, activity
|
37
|
-
- [ read, tie
|
38
|
-
sphere: organization
|
32
|
+
- [ represent ]
|
33
|
+
- [ create, activity ]
|
34
|
+
- [ read, activity ]
|
35
|
+
- [ read, tie ]
|
39
36
|
partner:
|
40
37
|
name: partner
|
41
|
-
parent: member # member is stronger than partner
|
42
38
|
permissions:
|
43
|
-
- [ read, activity
|
44
|
-
sphere: external_relations
|
45
|
-
|
39
|
+
- [ read, activity ]
|