From 154fd0b1ba93f022995a54c7b44987f52d1da800 Mon Sep 17 00:00:00 2001 From: Jens Kraemer Date: Fri, 10 Jun 2016 13:43:29 +0800 Subject: [PATCH] per role visibility settings for project and version custom fields --- app/models/project.rb | 7 +++++ app/models/project_custom_field.rb | 14 ++++++++++ app/models/version.rb | 32 ++++++++++++++++++++++ app/models/version_custom_field.rb | 9 ++++++ app/views/custom_fields/_form.html.erb | 24 ++-------------- .../_visibility_by_role_selector.html.erb | 21 ++++++++++++++ app/views/projects/_form.html.erb | 2 +- app/views/versions/_form.html.erb | 2 +- app/views/versions/index.api.rsb | 2 +- app/views/versions/show.api.rsb | 2 +- 10 files changed, 90 insertions(+), 25 deletions(-) create mode 100644 app/views/custom_fields/_visibility_by_role_selector.html.erb diff --git a/app/models/project.rb b/app/models/project.rb index c35a867..6b74e23 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -570,6 +570,13 @@ class Project < ActiveRecord::Base end end + def visible_custom_field_values(user = nil) + user ||= User.current + custom_field_values.select do |value| + value.custom_field.visible_by?(project, user) + end + end + def project self end diff --git a/app/models/project_custom_field.rb b/app/models/project_custom_field.rb index 2db4070..e6d5e77 100644 --- a/app/models/project_custom_field.rb +++ b/app/models/project_custom_field.rb @@ -19,4 +19,18 @@ class ProjectCustomField < CustomField def type_name :label_project_plural end + + def visible_by?(project, user=User.current) + super || (roles & user.roles_for_project(project)).present? + end + + def validate_custom_field + super + errors.add(:base, l(:label_role_plural) + ' ' + l('activerecord.errors.messages.blank')) unless visible? || roles.present? + end + + def visibility_by_project_condition(project_key=nil, user=User.current, id_column=nil) + project_key = 'projects.id' if project_key.blank? + super project_key, user, id_column + end end diff --git a/app/models/version.rb b/app/models/version.rb index 98d1c6a..d212712 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -68,11 +68,43 @@ class Version < ActiveRecord::Base 'custom_field_values', 'custom_fields' + def safe_attributes=(attrs, user = User.current) + return unless attrs.is_a?(Hash) + + attrs = delete_unsafe_attributes(attrs, user) + return if attrs.empty? + + if attrs['custom_field_values'].present? + editable_custom_field_ids = editable_custom_field_values(user).map {|v| v.custom_field_id.to_s} + attrs['custom_field_values'].reject! {|k, v| !editable_custom_field_ids.include?(k.to_s)} + end + + if attrs['custom_fields'].present? + editable_custom_field_ids = editable_custom_field_values(user).map {|v| v.custom_field_id.to_s} + attrs['custom_fields'].reject! {|c| !editable_custom_field_ids.include?(c['id'].to_s)} + end + + # mass-assignment security bypass + assign_attributes attrs, :without_protection => true + end + + # Returns the custom_field_values that can be edited by the given user + def editable_custom_field_values(user=nil) + visible_custom_field_values(user) + end + # Returns true if +user+ or current user is allowed to view the version def visible?(user=User.current) user.allowed_to?(:view_issues, self.project) end + def visible_custom_field_values(user = nil) + user ||= User.current + custom_field_values.select do |value| + value.custom_field.visible_by?(project, user) + end + end + # Version files have same visibility as project files def attachments_visible?(*args) project.present? && project.attachments_visible?(*args) diff --git a/app/models/version_custom_field.rb b/app/models/version_custom_field.rb index b6b1644..c4260ae 100644 --- a/app/models/version_custom_field.rb +++ b/app/models/version_custom_field.rb @@ -19,4 +19,13 @@ class VersionCustomField < CustomField def type_name :label_version_plural end + + def visible_by?(project, user=User.current) + super || (roles & user.roles_for_project(project)).present? + end + + def validate_custom_field + super + errors.add(:base, l(:label_role_plural) + ' ' + l('activerecord.errors.messages.blank')) unless visible? || roles.present? + end end diff --git a/app/views/custom_fields/_form.html.erb b/app/views/custom_fields/_form.html.erb index 7c79189..514b19a 100644 --- a/app/views/custom_fields/_form.html.erb +++ b/app/views/custom_fields/_form.html.erb @@ -32,26 +32,7 @@ when "IssueCustomField" %> <% if @custom_field.format.searchable_supported %>

<%= f.check_box :searchable %>

<% end %> -

- - - - <% Role.givable.sorted.each do |role| %> - - <% end %> - <%= hidden_field_tag 'custom_field[role_ids][]', '' %> -

+ <%= render :partial => 'visibility_by_role_selector' %> <% when "UserCustomField" %>

<%= f.check_box :is_required %>

@@ -61,15 +42,16 @@ when "IssueCustomField" %> <% when "ProjectCustomField" %>

<%= f.check_box :is_required %>

-

<%= f.check_box :visible %>

<% if @custom_field.format.searchable_supported %>

<%= f.check_box :searchable %>

<% end %>

<%= f.check_box :is_filter %>

+ <%= render :partial => 'visibility_by_role_selector' %> <% when "VersionCustomField" %>

<%= f.check_box :is_required %>

<%= f.check_box :is_filter %>

+ <%= render :partial => 'visibility_by_role_selector' %> <% when "GroupCustomField" %>

<%= f.check_box :is_required %>

diff --git a/app/views/custom_fields/_visibility_by_role_selector.html.erb b/app/views/custom_fields/_visibility_by_role_selector.html.erb new file mode 100644 index 0000000..4a498c1 --- /dev/null +++ b/app/views/custom_fields/_visibility_by_role_selector.html.erb @@ -0,0 +1,21 @@ +

+ + + + <% Role.givable.sorted.each do |role| %> + + <% end %> + <%= hidden_field_tag 'custom_field[role_ids][]', '' %> +

+ diff --git a/app/views/projects/_form.html.erb b/app/views/projects/_form.html.erb index 1e5917e..13c72ee 100644 --- a/app/views/projects/_form.html.erb +++ b/app/views/projects/_form.html.erb @@ -26,7 +26,7 @@ <%= wikitoolbar_for 'project_description' %> -<% @project.custom_field_values.each do |value| %> +<% @project.visible_custom_field_values.each do |value| %>

<%= custom_field_tag_with_label :project, value %>

<% end %> <%= call_hook(:view_projects_form, :project => @project, :form => f) %> diff --git a/app/views/versions/_form.html.erb b/app/views/versions/_form.html.erb index e723a4e..11b42dd 100644 --- a/app/views/versions/_form.html.erb +++ b/app/views/versions/_form.html.erb @@ -11,7 +11,7 @@

<%= f.date_field :effective_date, :size => 10 %><%= calendar_for('version_effective_date') %>

<%= f.select :sharing, @version.allowed_sharings.collect {|v| [format_version_sharing(v), v]} %>

-<% @version.custom_field_values.each do |value| %> +<% @version.visible_custom_field_values.each do |value| %>

<%= custom_field_tag_with_label :version, value %>

<% end %> diff --git a/app/views/versions/index.api.rsb b/app/views/versions/index.api.rsb index 3adde2b..5b0a80f 100644 --- a/app/views/versions/index.api.rsb +++ b/app/views/versions/index.api.rsb @@ -10,7 +10,7 @@ api.array :versions, api_meta(:total_count => @versions.size) do api.due_date version.effective_date api.sharing version.sharing - render_api_custom_values version.custom_field_values, api + render_api_custom_values version.visible_custom_field_values, api api.created_on version.created_on api.updated_on version.updated_on diff --git a/app/views/versions/show.api.rsb b/app/views/versions/show.api.rsb index 63bf2d3..c86f348 100644 --- a/app/views/versions/show.api.rsb +++ b/app/views/versions/show.api.rsb @@ -8,7 +8,7 @@ api.version do api.due_date @version.effective_date api.sharing @version.sharing - render_api_custom_values @version.custom_field_values, api + render_api_custom_values @version.visible_custom_field_values, api api.created_on @version.created_on api.updated_on @version.updated_on -- 2.1.4