From fcb7b6e8ccb692e029710d1bffcc32cbfeb66699 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Vilain Date: Wed, 19 Jun 2013 19:08:13 +0200 Subject: [PATCH] SONAR-4099 Added new global permission to enable dashboard sharing for non-admin users --- .../resources/org/sonar/l10n/core.properties | 8 ++-- .../core/persistence/DatabaseVersion.java | 2 +- .../org/sonar/core/persistence/rows-h2.sql | 4 +- .../app/controllers/dashboards_controller.rb | 40 +++++++++--------- .../app/controllers/measures_controller.rb | 2 +- .../webapp/WEB-INF/app/models/dashboard.rb | 16 ++++++++ .../WEB-INF/app/models/measure_filter.rb | 4 ++ .../main/webapp/WEB-INF/app/models/role.rb | 22 ---------- .../views/dashboards/_create_form.html.erb | 4 +- .../app/views/dashboards/_edit_form.html.erb | 14 ++++++- .../app/views/layouts/_layout.html.erb | 2 +- .../app/views/measures/_edit_form.html.erb | 4 +- .../WEB-INF/app/views/roles/global.html.erb | 4 +- .../413_add_dashboard_sharing_permission.rb | 41 +++++++++++++++++++ .../webapp/WEB-INF/lib/need_authorization.rb | 2 +- 15 files changed, 110 insertions(+), 59 deletions(-) delete mode 100644 sonar-server/src/main/webapp/WEB-INF/app/models/role.rb create mode 100644 sonar-server/src/main/webapp/WEB-INF/db/migrate/413_add_dashboard_sharing_permission.rb diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties index fc6c3b895ad..377c43aba48 100644 --- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties +++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties @@ -332,7 +332,7 @@ sidebar.tools=Tools #------------------------------------------------------------------------------ action_plans.page=Action Plans -administrators.page=Administrators +global_permissions.page=Global Permissions backup.page=Backup clouds.page=Clouds components.page=Components @@ -2186,10 +2186,12 @@ metric.confirmed_issues.description=Confirmed issues global_role.role=Role global_role.users=Users global_role.groups=Groups -global_role.admin=System Administrators +global_role.admin=System Administration global_role.admin.desc=Ability to perform all administration functions for the instance: global configuration and personalization of default dashboards. -global_role.profileadmin=Quality Profile Administrators +global_role.profileadmin=Quality Profile Administration global_role.profileadmin.desc=Ability to perform any action on the quality profiles. +global_role.sharedashboard=Dashboard Sharing +global_role.sharedashboard.desc=Ability to share eligible dashboards. #------------------------------------------------------------------------------ diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java index 85fb8a3f1ad..edcbbc9969c 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java @@ -32,7 +32,7 @@ import java.util.List; */ public class DatabaseVersion implements BatchComponent, ServerComponent { - public static final int LAST_VERSION = 412; + public static final int LAST_VERSION = 413; public static enum Status { UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql index 1d75faef1a7..4e43875c862 100644 --- a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql +++ b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql @@ -6,7 +6,8 @@ ALTER TABLE GROUPS ALTER COLUMN ID RESTART WITH 3; INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (1, 1, null, 'admin'); INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (2, 1, null, 'profileadmin'); -ALTER TABLE GROUP_ROLES ALTER COLUMN ID RESTART WITH 3; +INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (3, 1, null, 'sharedashboard'); +ALTER TABLE GROUP_ROLES ALTER COLUMN ID RESTART WITH 4; INSERT INTO GROUPS_USERS(USER_ID, GROUP_ID) VALUES (1, 1); INSERT INTO GROUPS_USERS(USER_ID, GROUP_ID) VALUES (1, 2); @@ -172,6 +173,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('405'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('410'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('411'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('412'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('413'); INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null); ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2; diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/dashboards_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/dashboards_controller.rb index ca949ed9e89..01fbc469a69 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/dashboards_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/dashboards_controller.rb @@ -59,19 +59,15 @@ class DashboardsController < ApplicationController active_dashboard = current_user.active_dashboards.to_a.find { |ad| ad.name==@dashboard.name } if active_dashboard - flash[:error]=Api::Utils.message('dashboard.error_create_existing_name') - - redirect_to :action => 'index', :resource => params[:resource] + @dashboard.errors.add(Api::Utils.message('dashboard.error_create_existing_name')) + render :partial => 'dashboards/create_form', :status => 400, :resource => params[:resource] elsif @dashboard.save add_default_dashboards_if_first_user_dashboard(@dashboard.global?) last_index=current_user.active_dashboards.max_by(&:order_index).order_index current_user.active_dashboards.create(:dashboard => @dashboard, :user => current_user, :order_index => (last_index+1)) - - redirect_to :action => 'index', :resource => params[:resource], :highlight => @dashboard.id + render :text => @dashboard.id.to_s, :resource => params[:resource], :highlight => @dashboard.id, :status => 200 else - flash[:error]=@dashboard.errors.full_messages.join('
') - - redirect_to :action => 'index', :resource => params[:resource] + render :partial => 'dashboards/create_form', :status => 400, :resource => params[:resource] end end @@ -86,16 +82,18 @@ class DashboardsController < ApplicationController def update verify_post_request - dashboard=Dashboard.find(params[:id]) - if dashboard.editable_by?(current_user) - load_dashboard_from_params(dashboard) - - unless dashboard.save - flash[:error]=dashboard.errors.full_messages.join('
') + @dashboard = Dashboard.find(params[:id]) + if @dashboard.editable_by?(current_user) + load_dashboard_from_params(@dashboard) + if @dashboard.save + render :text => @dashboard.id.to_s, :resource => params[:resource], :status => 200 + else + render :partial => 'dashboards/edit_form', :status => 400, :resource => params[:resource] end + else + # TODO - notify error ? + render :text => @dashboard.id.to_s, :resource => params[:resource], :status => 200 end - - redirect_to :action => 'index', :resource => params[:resource] end def delete_form @@ -184,11 +182,11 @@ class DashboardsController < ApplicationController end def load_dashboard_from_params(dashboard) - dashboard.name=params[:name] - dashboard.description=params[:description] - dashboard.is_global=(params[:global].present?) - dashboard.shared=(params[:shared].present? && is_admin?) - dashboard.column_layout=Dashboard::DEFAULT_LAYOUT if !dashboard.column_layout + dashboard.name = params[:name] + dashboard.description = params[:description] + dashboard.is_global = params[:global].present? + dashboard.shared = params[:shared].present? && has_role?(:sharedashboard) + dashboard.column_layout = Dashboard::DEFAULT_LAYOUT if !dashboard.column_layout dashboard.user = User.find_active_by_login(params[:owner]) unless params[:owner].nil? end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/measures_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/measures_controller.rb index 2aea260bac5..9f93c3e3b5f 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/measures_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/measures_controller.rb @@ -141,7 +141,7 @@ class MeasuresController < ApplicationController @filter.description=params[:description] @filter.shared=(params[:shared]=='true') - if has_role?(:admin) + if has_role?(:admin) && params[:owner] @filter.user = User.find_by_login(params[:owner]) end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/dashboard.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/dashboard.rb index f4337a54e6d..1ee10af6bf7 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/dashboard.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/dashboard.rb @@ -32,6 +32,8 @@ class Dashboard < ActiveRecord::Base validates_uniqueness_of :name, :scope => :user_id validates_inclusion_of :is_global, :in => [true, false] + validate :user_rights_consistency + before_destroy :check_not_default_before_destroy def name(l10n=false) @@ -43,6 +45,12 @@ class Dashboard < ActiveRecord::Base end end + def user_rights_consistency + if shared? && !user.has_role?(:sharedashboard) + errors.add(:user, "cannot own this dashboard because it has insufficient rights") + end + end + def shared? read_attribute(:shared) || false end @@ -75,6 +83,14 @@ class Dashboard < ActiveRecord::Base self.user_id==user.id end + def can_be_shared_by(user) + owner?(user) && user.has_role?(:sharedashboard) + end + + def can_be_reassigned_by(user) + shared? && user.has_role?(:admin) + end + def number_of_columns column_layout.split('-').size end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/measure_filter.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/measure_filter.rb index 2eeb1828ba1..1f4bb44e29e 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/measure_filter.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/measure_filter.rb @@ -98,6 +98,10 @@ class MeasureFilter < ActiveRecord::Base criteria[:onFavourites]=='true' end + def can_be_reassigned_by(user) + user.has_role?(:admin) && shared + end + def criteria(key=nil) @criteria ||= HashWithIndifferentAccess.new if key diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/role.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/role.rb deleted file mode 100644 index 7778badb856..00000000000 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/role.rb +++ /dev/null @@ -1,22 +0,0 @@ - # - # Sonar, entreprise quality control tool. - # Copyright (C) 2008-2013 SonarSource - # mailto:contact AT sonarsource DOT com - # - # SonarQube is free software; you can redistribute it and/or - # modify it under the terms of the GNU Lesser General Public - # License as published by the Free Software Foundation; either - # version 3 of the License, or (at your option) any later version. - # - # SonarQube is distributed in the hope that it will be useful, - # but WITHOUT ANY WARRANTY; without even the implied warranty of - # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - # Lesser General Public License for more details. - # - # You should have received a copy of the GNU Lesser General Public License - # along with this program; if not, write to the Free Software Foundation, - # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - # -class Role < ActiveRecord::Base - ADMIN = 'sonar_admin' -end \ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/dashboards/_create_form.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/dashboards/_create_form.html.erb index a570962e753..13606eac007 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/dashboards/_create_form.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/dashboards/_create_form.html.erb @@ -11,7 +11,7 @@