Commit bdaf45c2917613b64fbdd5ecb0458cfe3078cdbc
Exists in
master
and in
25 other branches
Merge branch 'view_tasks_permission' into 'master'
New permission 'view_tasks' that allow only tasks visualization See merge request !588
Showing
9 changed files
with
164 additions
and
18 deletions
Show diff stats
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 < MyProfileController | @@ -15,6 +16,8 @@ class TasksController < 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 < ActiveRecord::Base | @@ -75,7 +75,8 @@ class Environment < 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 < ActiveRecord::Base | @@ -71,6 +71,7 @@ class Profile < 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 < ActionController::TestCase | @@ -520,4 +520,114 @@ class TasksControllerTest < 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 < ActionController::TestCase | @@ -28,9 +28,20 @@ class PermissionCheckTest < 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 < ApplicationController | @@ -41,6 +41,8 @@ class AccessControlTestController < 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 < ApplicationController | @@ -49,6 +51,10 @@ class AccessControlTestController < 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] |