aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties8
-rw-r--r--sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java2
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql4
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/controllers/dashboards_controller.rb40
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/controllers/measures_controller.rb2
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/dashboard.rb16
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/measure_filter.rb4
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/role.rb22
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/dashboards/_create_form.html.erb4
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/dashboards/_edit_form.html.erb14
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb2
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/measures/_edit_form.html.erb4
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/roles/global.html.erb4
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/db/migrate/413_add_dashboard_sharing_permission.rb41
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/lib/need_authorization.rb2
15 files changed, 110 insertions, 59 deletions
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('<br/>')
-
- 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('<br/>')
+ @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 @@
<div class="modal-body">
<% if @dashboard %>
<% @dashboard.errors.each do |attr, msg| %>
- <p class="error"><%= h msg -%></p>
+ <p class="error"><%= h "#{attr} #{msg}" -%></p>
<% end %>
<% end %>
<div class="modal-field">
@@ -22,7 +22,7 @@
<label for="description"><%= h message('description') -%></label>
<input id="description" name="description" type="text" size="50" maxlength="4000" value="<%= h @dashboard.description -%>"/>
</div>
- <% if is_admin? %>
+ <% if has_role?(:sharedashboard) %>
<div class="modal-field">
<label for="shared"><%= h message('shared') -%></label>
<input id="shared" name="shared" type="checkbox" value="true" <%= 'checked' if @dashboard.shared -%>/>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/dashboards/_edit_form.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/dashboards/_edit_form.html.erb
index faa26a54363..ee8aab60363 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/dashboards/_edit_form.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/dashboards/_edit_form.html.erb
@@ -11,7 +11,7 @@
</div>
<div class="modal-body">
<% @dashboard.errors.each do |attr, msg| %>
- <p class="error"><%= h msg -%></p>
+ <p class="error"><%= h "#{attr} #{msg}" -%></p>
<% end %>
<div class="modal-field">
<label for="name"><%= h message('name') -%> <em class="mandatory">*</em></label>
@@ -21,15 +21,19 @@
<label for="description"><%= h message('description') -%></label>
<input id="description" name="description" type="text" size="50" maxlength="4000" value="<%= h @dashboard.description -%>"/>
</div>
- <% if is_admin? %>
+ <% if @dashboard.can_be_reassigned_by(current_user) %>
<div class="modal-field">
<label for="owner"><%= h message('owner') -%></label>
<%= user_select_tag('owner', :html_id => 'select-dashboard-owner', :selected_user => @dashboard.user) -%>
</div>
+ <% end %>
+ <% if @dashboard.can_be_shared_by(current_user) %>
<div class="modal-field">
<label for="shared"><%= h message('shared') -%></label>
<input id="shared" name="shared" type="checkbox" value="true" <%= 'checked' if @dashboard.shared -%>/>
</div>
+ <% else %>
+ <input id="shared" name="shared" type="hidden" value="<%= @dashboard.shared %>"/>
<% end %>
</div>
<div class="modal-foot">
@@ -38,3 +42,9 @@
</div>
</fieldset>
</form>
+
+<script>
+ $j("#edit-dashboard-form").modalForm({success: function (data) {
+ window.location = baseUrl + '/dashboards';
+ }});
+</script> \ No newline at end of file
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb
index b5eb71a2b68..43aff0bae81 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb
@@ -130,7 +130,7 @@
<li class="<%= 'active' if request.request_uri.include?('/groups') -%>">
<a href="<%= ApplicationController.root_context -%>/groups/index"><%= message('user_groups.page') -%></a></li>
<li class="<%= 'active' if request.request_uri.include?('/roles/global') -%>">
- <a href="<%= ApplicationController.root_context -%>/roles/global"><%= message('administrators.page') -%></a></li>
+ <a href="<%= ApplicationController.root_context -%>/roles/global"><%= message('global_permissions.page') -%></a></li>
<li class="<%= 'active' if request.request_uri.include?('/roles/projects') -%>">
<a href="<%= ApplicationController.root_context -%>/roles/projects"><%= message('roles.page') -%></a></li>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/measures/_edit_form.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/measures/_edit_form.html.erb
index 7465c6f8ec0..5b9f6b43984 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/measures/_edit_form.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/measures/_edit_form.html.erb
@@ -6,7 +6,7 @@
</div>
<div class="modal-body">
<% @filter.errors.each do |attr, msg| %>
- <p class="error"><%= h msg -%></p>
+ <p class="error"><%= h "#{attr} #{msg}" -%></p>
<% end %>
<div class="modal-field">
<label for="name"><%= h message('name') -%> <em class="mandatory">*</em></label>
@@ -16,7 +16,7 @@
<label for="description"><%= h message('description') -%></label>
<input id="description" name="description" type="text" size="50" maxlength="4000" value="<%= h @filter.description -%>"/>
</div>
- <% if is_admin? %>
+ <% if @filter.can_be_reassigned_by(current_user) %>
<div class="modal-field">
<label for="owner"><%= h message('owner') -%></label>
<%= user_select_tag('owner', :html_id => 'select-filter-owner', :selected_user => @filter.user) -%>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/roles/global.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/roles/global.html.erb
index ad41fea07da..912ea799922 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/roles/global.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/roles/global.html.erb
@@ -1,4 +1,4 @@
-<h1 class="marginbottom10"><%= message 'administrators.page' -%></h1>
+<h1 class="marginbottom10"><%= message 'global_permissions.page' -%></h1>
<table class="data width100" id="global-roles">
<thead>
@@ -9,7 +9,7 @@
</tr>
</thead>
<tbody>
- <% ['admin', 'profileadmin'].each do |globalRole| %>
+ <% ['admin', 'profileadmin', 'sharedashboard'].each do |globalRole| %>
<tr class="<%= cycle('even', 'odd', :name => 'globalRole') -%>" >
<td valign="top">
<b><%= message('global_role.' + globalRole) -%></b><br/>
diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/413_add_dashboard_sharing_permission.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/413_add_dashboard_sharing_permission.rb
new file mode 100644
index 00000000000..978f598220d
--- /dev/null
+++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/413_add_dashboard_sharing_permission.rb
@@ -0,0 +1,41 @@
+#
+# 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.
+#
+
+#
+# Sonar 3.7
+#
+
+class AddDashboardSharingPermission < ActiveRecord::Migration
+
+ def self.up
+ group_roles=GroupRole.find(:all, :conditions => {:role => 'admin', :resource_id => nil})
+ groups = group_roles.map { |ur| ur.group_id }
+ groups.each do |group_id|
+ GroupRole.create(:group_id => group_id, :role => 'sharedashboard', :resource_id => nil)
+ end
+
+ user_roles=UserRole.find(:all, :conditions => {:role => 'admin', :resource_id => nil})
+ users = user_roles.map { |ur| ur.user_id }
+ users.each do |user_id|
+ UserRole.create(:user_id => user_id, :role=> 'sharedashboard', :resource_id => nil)
+ end
+ end
+
+end
diff --git a/sonar-server/src/main/webapp/WEB-INF/lib/need_authorization.rb b/sonar-server/src/main/webapp/WEB-INF/lib/need_authorization.rb
index 9d3dd68193a..1deab73eb62 100644
--- a/sonar-server/src/main/webapp/WEB-INF/lib/need_authorization.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/lib/need_authorization.rb
@@ -59,7 +59,7 @@ module NeedAuthorization
def has_role?(role, objects=nil)
if objects.nil?
role_symbol=role.to_sym
- if role_symbol==:admin || role_symbol==:profileadmin
+ if role_symbol==:admin || role_symbol==:profileadmin || role_symbol==:sharedashboard
AuthorizerFactory.authorizer.has_role?(self, role_symbol)
else
# There's no concept of global users or global codeviewers.