Commit bdaf45c2917613b64fbdd5ecb0458cfe3078cdbc

Authored by Leandro Santos
2 parents 790467eb d01c42a2

Merge branch 'view_tasks_permission' into 'master'

New permission 'view_tasks' that allow only tasks visualization

See merge request !588
app/controllers/my_profile/tasks_controller.rb
1 class TasksController < MyProfileController 1 class TasksController < MyProfileController
2 2
3 - protect 'perform_task', :profile 3 + protect [:perform_task, :view_tasks], :profile, :only => [:index]
  4 + protect :perform_task, :profile, :except => [:index]
4 5
5 def index 6 def index
6 @filter_type = params[:filter_type].presence 7 @filter_type = params[:filter_type].presence
@@ -15,6 +16,8 @@ class TasksController &lt; MyProfileController @@ -15,6 +16,8 @@ class TasksController &lt; MyProfileController
15 @failed = params ? params[:failed] : {} 16 @failed = params ? params[:failed] : {}
16 17
17 @responsible_candidates = profile.members.by_role(profile.roles.reject {|r| !r.has_permission?('perform_task')}) if profile.organization? 18 @responsible_candidates = profile.members.by_role(profile.roles.reject {|r| !r.has_permission?('perform_task')}) if profile.organization?
  19 +
  20 + @view_only = !current_person.has_permission?(:perform_task, profile)
18 end 21 end
19 22
20 def processed 23 def processed
app/models/environment.rb
@@ -75,7 +75,8 @@ class Environment &lt; ActiveRecord::Base @@ -75,7 +75,8 @@ class Environment &lt; ActiveRecord::Base
75 'edit_profile_design', 75 'edit_profile_design',
76 'manage_products', 76 'manage_products',
77 'manage_friends', 77 'manage_friends',
78 - 'perform_task' 78 + 'perform_task',
  79 + 'view_tasks'
79 ] 80 ]
80 ) 81 )
81 end 82 end
app/models/profile.rb
@@ -71,6 +71,7 @@ class Profile &lt; ActiveRecord::Base @@ -71,6 +71,7 @@ class Profile &lt; ActiveRecord::Base
71 'manage_friends' => N_('Manage friends'), 71 'manage_friends' => N_('Manage friends'),
72 'validate_enterprise' => N_('Validate enterprise'), 72 'validate_enterprise' => N_('Validate enterprise'),
73 'perform_task' => N_('Perform task'), 73 'perform_task' => N_('Perform task'),
  74 + 'view_tasks' => N_('View tasks'),
74 'moderate_comments' => N_('Moderate comments'), 75 'moderate_comments' => N_('Moderate comments'),
75 'edit_appearance' => N_('Edit appearance'), 76 'edit_appearance' => N_('Edit appearance'),
76 'view_private_content' => N_('View private content'), 77 'view_private_content' => N_('View private content'),
app/views/tasks/_task.html.erb
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 2
3 <%= render :partial => 'task_icon', :locals => {:task => task} %> 3 <%= render :partial => 'task_icon', :locals => {:task => task} %>
4 4
5 - <% if profile.organization? && @responsible_candidates.present? %> 5 + <% if !@view_only && profile.organization? && @responsible_candidates.present? %>
6 <div class="task_responsible"> 6 <div class="task_responsible">
7 <span class="label"><%= _('Assign to:') %></span> 7 <span class="label"><%= _('Assign to:') %></span>
8 <span> 8 <span>
@@ -12,8 +12,16 @@ @@ -12,8 +12,16 @@
12 </div> 12 </div>
13 <% end %> 13 <% end %>
14 14
  15 + <% if @view_only && task.responsible.present? %>
  16 + <div class="task_responsible">
  17 + <span class="label"><%= _('Assigned to:') %></span>
  18 + <span class="value"><%= task.responsible.name %></span>
  19 + </div>
  20 + <% end %>
  21 +
15 <div class="task_decisions"> 22 <div class="task_decisions">
16 - <%= 23 + <% unless @view_only %>
  24 + <%=
17 labelled_radio_button(_("Accept"), "tasks[#{task.id}][decision]", 'finish', task.default_decision == 'accept', 25 labelled_radio_button(_("Accept"), "tasks[#{task.id}][decision]", 'finish', task.default_decision == 'accept',
18 :id => "decision-finish-#{task.id}", 26 :id => "decision-finish-#{task.id}",
19 :class => 'task_accept_radio', 27 :class => 'task_accept_radio',
@@ -29,7 +37,8 @@ @@ -29,7 +37,8 @@
29 :class => 'task_skip_radio', 37 :class => 'task_skip_radio',
30 :disabled => task.skip_disabled?, 38 :disabled => task.skip_disabled?,
31 :task_id => "#{task.id}") 39 :task_id => "#{task.id}")
32 - %> 40 + %>
  41 + <% end %>
33 </div><!-- class="task_decisions" --> 42 </div><!-- class="task_decisions" -->
34 43
35 <div class="task_date"><%= show_time(task.created_at) %></div> 44 <div class="task_date"><%= show_time(task.created_at) %></div>
app/views/tasks/index.html.erb
@@ -46,36 +46,41 @@ @@ -46,36 +46,41 @@
46 </p> 46 </p>
47 <% else %> 47 <% else %>
48 <%= form_tag :action => 'close' do%> 48 <%= form_tag :action => 'close' do%>
49 - <% button_bar do %> 49 + <% button_bar(:class => 'task-actions') do %>
50 <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %> 50 <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %>
51 <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %> 51 <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %>
52 <%= submit_button :save, _("Apply!") %> 52 <%= submit_button :save, _("Apply!") %>
53 <%= button(:edit, _('View processed tasks'), :action => 'processed') %> 53 <%= button(:edit, _('View processed tasks'), :action => 'processed') %>
54 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> 54 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %>
55 - <% end %> 55 + <% end unless @view_only %>
56 56
57 <ul class='task-list'> 57 <ul class='task-list'>
58 - <p>  
59 - <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "up-set-all-tasks-to") %>  
60 - </p> 58 + <% unless @view_only %>
  59 + <p>
  60 + <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "up-set-all-tasks-to") %>
  61 + </p>
  62 + <% end %>
61 63
62 <div class="task_boxes"> 64 <div class="task_boxes">
63 <%= render :partial => 'task', :collection => @tasks %> 65 <%= render :partial => 'task', :collection => @tasks %>
64 </div> 66 </div>
65 - <p>  
66 - <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "down-set-all-tasks-to") %>  
67 - </p> 67 +
  68 + <% unless @view_only %>
  69 + <p>
  70 + <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "down-set-all-tasks-to") %>
  71 + </p>
  72 + <% end %>
68 </ul> 73 </ul>
69 74
70 <%= pagination_links(@tasks)%> 75 <%= pagination_links(@tasks)%>
71 76
72 - <% button_bar do %> 77 + <% button_bar(:class => 'task-actions') do %>
73 <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %> 78 <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %>
74 <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %> 79 <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %>
75 <%= submit_button :save, _("Apply!") %> 80 <%= submit_button :save, _("Apply!") %>
76 <%= button(:edit, _('View processed tasks'), :action => 'processed') %> 81 <%= button(:edit, _('View processed tasks'), :action => 'processed') %>
77 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> 82 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %>
78 - <% end %> 83 + <% end unless @view_only %>
79 <% end %> 84 <% end %>
80 <% end %> 85 <% end %>
81 </p> 86 </p>
test/functional/tasks_controller_test.rb
@@ -520,4 +520,114 @@ class TasksControllerTest &lt; ActionController::TestCase @@ -520,4 +520,114 @@ class TasksControllerTest &lt; ActionController::TestCase
520 assert !json_response['success'] 520 assert !json_response['success']
521 end 521 end
522 522
  523 + should 'list tasks for user with only view_tasks permission' do
  524 + community = fast_create(Community)
  525 + @controller.stubs(:profile).returns(community)
  526 + person = create_user_with_permission('taskviewer', 'view_tasks', community)
  527 + login_as person.user.login
  528 + get :index
  529 + assert_response :success
  530 + assert assigns(:view_only)
  531 + end
  532 +
  533 + should 'forbid user with only view_tasks permission to close a task' do
  534 + community = fast_create(Community)
  535 + @controller.stubs(:profile).returns(community)
  536 + person = create_user_with_permission('taskviewer', 'view_tasks', community)
  537 + login_as person.user.login
  538 + post :close
  539 + assert_response 403
  540 + end
  541 +
  542 + should 'hide tasks actions when user has only view_tasks permission' do
  543 + community = fast_create(Community)
  544 + @controller.stubs(:profile).returns(community)
  545 + person = create_user_with_permission('taskviewer', 'view_tasks', community)
  546 + login_as person.user.login
  547 +
  548 + Task.create!(:requestor => person, :target => community)
  549 + get :index
  550 +
  551 + assert_select '.task-actions', 0
  552 + end
  553 +
  554 + should 'display tasks actions when user has perform_task permission' do
  555 + community = fast_create(Community)
  556 + @controller.stubs(:profile).returns(community)
  557 + person = create_user_with_permission('taskperformer', 'perform_task', community)
  558 + login_as person.user.login
  559 +
  560 + Task.create!(:requestor => person, :target => community)
  561 + get :index
  562 +
  563 + assert_select '.task-actions', 2
  564 + end
  565 +
  566 + should 'hide decision selector when user has only view_tasks permission' do
  567 + community = fast_create(Community)
  568 + @controller.stubs(:profile).returns(community)
  569 + person = create_user_with_permission('taskviewer', 'view_tasks', community)
  570 + login_as person.user.login
  571 +
  572 + Task.create!(:requestor => person, :target => community)
  573 + get :index
  574 +
  575 + assert_select '#up-set-all-tasks-to', 0
  576 + assert_select '#down-set-all-tasks-to', 0
  577 + end
  578 +
  579 + should 'display decision selector when user has perform_task permission' do
  580 + community = fast_create(Community)
  581 + @controller.stubs(:profile).returns(community)
  582 + person = create_user_with_permission('taskperformer', 'perform_task', community)
  583 + login_as person.user.login
  584 +
  585 + Task.create!(:requestor => person, :target => community)
  586 + get :index
  587 +
  588 + assert_select '#up-set-all-tasks-to'
  589 + assert_select '#down-set-all-tasks-to'
  590 + end
  591 +
  592 + should 'hide decision buttons when user has only view_tasks permission' do
  593 + community = fast_create(Community)
  594 + @controller.stubs(:profile).returns(community)
  595 + person = create_user_with_permission('taskviewer', 'view_tasks', community)
  596 + login_as person.user.login
  597 +
  598 + task = Task.create!(:requestor => person, :target => community)
  599 + get :index
  600 +
  601 + assert_select "#decision-finish-#{task.id}", 0
  602 + assert_select "#decision-cancel-#{task.id}", 0
  603 + assert_select "#decision-skip-#{task.id}", 0
  604 + end
  605 +
  606 + should 'display decision buttons when user has perform_task permission' do
  607 + community = fast_create(Community)
  608 + @controller.stubs(:profile).returns(community)
  609 + person = create_user_with_permission('taskperformer', 'perform_task', community)
  610 + login_as person.user.login
  611 +
  612 + task = Task.create!(:requestor => person, :target => community)
  613 + get :index
  614 +
  615 + assert_select "#decision-finish-#{task.id}"
  616 + assert_select "#decision-cancel-#{task.id}"
  617 + assert_select "#decision-skip-#{task.id}"
  618 + end
  619 +
  620 + should 'hide responsive selection when user has only view_tasks permission' do
  621 + community = fast_create(Community)
  622 + @controller.stubs(:profile).returns(community)
  623 + person = create_user_with_permission('taskviewer', 'view_tasks', community)
  624 + login_as person.user.login
  625 +
  626 + task = Task.create!(:requestor => person, :target => community, :responsible => person)
  627 + get :index
  628 +
  629 + assert_select ".task_responsible select", 0
  630 + assert_select ".task_responsible .value"
  631 + end
  632 +
523 end 633 end
vendor/plugins/access_control/lib/permission_check.rb
@@ -19,7 +19,7 @@ module PermissionCheck @@ -19,7 +19,7 @@ module PermissionCheck
19 before_filter actions do |c| 19 before_filter actions do |c|
20 target = target_method.kind_of?(Symbol) ? c.send(target_method) : target_method 20 target = target_method.kind_of?(Symbol) ? c.send(target_method) : target_method
21 accessor = accessor_method.kind_of?(Symbol) ? c.send(accessor_method) : accessor_method 21 accessor = accessor_method.kind_of?(Symbol) ? c.send(accessor_method) : accessor_method
22 - unless accessor && accessor.has_permission?(permission.to_s, target) 22 + unless Array.wrap(permission).map {|p| accessor && accessor.has_permission?(p.to_s, target)}.any?
23 c.class.render_access_denied(c) && false 23 c.class.render_access_denied(c) && false
24 end 24 end
25 end 25 end
vendor/plugins/access_control/test/permission_check_test.rb
@@ -28,9 +28,20 @@ class PermissionCheckTest &lt; ActionController::TestCase @@ -28,9 +28,20 @@ class PermissionCheckTest &lt; ActionController::TestCase
28 end 28 end
29 29
30 def test_try_render_shared_access_denied_view 30 def test_try_render_shared_access_denied_view
31 - File.expects(:exists?).with(File.join(Rails.root, 'app', 'views', 'access_control', 'access_denied.rhtml'))  
32 - File.expects(:exists?).with(File.join(Rails.root, 'app', 'views', 'shared', 'access_denied.rhtml')) 31 + File.expects(:exists?).with(File.join(Rails.root, 'app', 'views', 'access_control', 'access_denied.html.erb'))
  32 + File.expects(:exists?).with(File.join(Rails.root, 'app', 'views', 'shared', 'access_denied.html.erb'))
33 AccessControlTestController.access_denied_template_path 33 AccessControlTestController.access_denied_template_path
34 end 34 end
35 35
  36 + def test_allow_access_to_user_with_one_of_multiple_permissions
  37 + user = AccessControlTestAccessor.create!(:name => 'other_user')
  38 + role = Role.create!(:name => 'other_role', :permissions => ['permission1'])
  39 + resource = AccessControlTestResource.create!(:name => 'some_resource')
  40 + assert user.add_role(role, resource)
  41 + assert user.has_permission?('permission1', resource)
  42 +
  43 + get :stuff_with_multiple_permission, :user => user.id, :resource => resource.id
  44 + assert_response :success
  45 + end
  46 +
36 end 47 end
vendor/plugins/access_control/test/test_helper.rb
@@ -41,6 +41,8 @@ class AccessControlTestController &lt; ApplicationController @@ -41,6 +41,8 @@ class AccessControlTestController &lt; ApplicationController
41 include PermissionCheck 41 include PermissionCheck
42 protect 'see_index', 'global', :user, :only => :index 42 protect 'see_index', 'global', :user, :only => :index
43 protect 'do_some_stuff', :resource, :user, :only => :other_stuff 43 protect 'do_some_stuff', :resource, :user, :only => :other_stuff
  44 + protect ['permission1', 'permission2'], :resource, :user, :only => :stuff_with_multiple_permission
  45 +
44 def index 46 def index
45 render :text => 'test controller' 47 render :text => 'test controller'
46 end 48 end
@@ -49,6 +51,10 @@ class AccessControlTestController &lt; ApplicationController @@ -49,6 +51,10 @@ class AccessControlTestController &lt; ApplicationController
49 render :text => 'test stuff' 51 render :text => 'test stuff'
50 end 52 end
51 53
  54 + def stuff_with_multiple_permission
  55 + render :text => 'multiple permission'
  56 + end
  57 +
52 protected 58 protected
53 def user 59 def user
54 AccessControlTestAccessor.find(params[:user]) if params[:user] 60 AccessControlTestAccessor.find(params[:user]) if params[:user]