#------------------------------------------------------------------------------
action_plans.page=Action Plans
-administrators.page=Administrators
+global_permissions.page=Global Permissions
backup.page=Backup
clouds.page=Clouds
components.page=Components
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.
#------------------------------------------------------------------------------
*/
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
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);
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;
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
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
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
@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
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)
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
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
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
+++ /dev/null
- #
- # 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
<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">
<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 -%>/>
</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>
<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">
</div>
</fieldset>
</form>
+
+<script>
+ $j("#edit-dashboard-form").modalForm({success: function (data) {
+ window.location = baseUrl + '/dashboards';
+ }});
+</script>
\ No newline at end of file
<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>
</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>
<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) -%>
-<h1 class="marginbottom10"><%= message 'administrators.page' -%></h1>
+<h1 class="marginbottom10"><%= message 'global_permissions.page' -%></h1>
<table class="data width100" id="global-roles">
<thead>
</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/>
--- /dev/null
+#
+# 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
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.