Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataProviders: restriction panels: new toggles and defaults #1390

Open
wants to merge 12 commits into
base: dev
Choose a base branch
from
Open
9 changes: 9 additions & 0 deletions BrainPortal/app/assets/stylesheets/cbrain.css.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2655,3 +2655,12 @@ img {
.no-close .ui-dialog-titlebar-close {
display: none;
}

.indeterminate {
color: steelblue !important;
}

.indeterminate_box_label {
color: steelblue !important;
font-weight: normal !important;
}
6 changes: 4 additions & 2 deletions BrainPortal/app/controllers/data_providers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,11 @@ def update #:nodoc:

# Fields that stay the same if the form provides a blank entry:
new_data_provider_attr.delete :cloud_storage_client_token if new_data_provider_attr[:cloud_storage_client_token].blank?
if @provider.update_attributes_with_logging(new_data_provider_attr, current_user, @provider.attributes.keys + [])
mass_flags = 'dp_no_copy_default|rr_no_sync_default' # default policies w.r.t new dp or server
# todo cast params to hash for rails 5.1 as `ActionController::Parameters` no longer inherits from hash
meta_flags_for_restrictions = (params[:meta] || {}).keys.grep(/\Adp_no_copy_\d+\z|\Arr_no_sync_\d+|#{mass_flags}\z/)

if @provider.update_attributes_with_logging(new_data_provider_attr, current_user, @provider.attributes.keys)
meta_flags_for_restrictions = (params[:meta] || {}).keys.grep(/\Adp_no_copy_\d+\z|\Arr_no_sync_\d+\z/)
add_meta_data_from_form(@provider, [:must_move, :no_uploads, :no_viewers, :browse_gid] + meta_flags_for_restrictions)
flash[:notice] = "Provider successfully updated."
respond_to do |format|
Expand Down
4 changes: 3 additions & 1 deletion BrainPortal/app/helpers/show_table_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,14 @@ def edit_cell(field, options = {}, &block)
# As +boolean_edit_cell+ is a specialization of +edit_cell+, +field+,
# +&block+ and +options+ are handled the same way (save for the defaults
# outlined above).
# +input_options+ are options just for the checkbox itself (at the moment apply only to the edit mode and block-free use)
def boolean_edit_cell(field, cur_value, checked_value = "1", unchecked_value = "0", options = {}, &block)
options[:content] ||= @template.disabled_checkbox(cur_value == checked_value)
input_options = options.delete(:input_options) || {}
if block_given?
edit_cell(field, options, &block)
else
edit_cell(field, options) { @template.hidden_field_tag(field, unchecked_value) + @template.check_box_tag(field, checked_value, cur_value == checked_value) }
edit_cell(field, options) { @template.hidden_field_tag(field, unchecked_value) + @template.check_box_tag(field, checked_value, cur_value == checked_value, input_options) }
end
end

Expand Down
22 changes: 15 additions & 7 deletions BrainPortal/app/models/data_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1361,11 +1361,13 @@ def self.cleanup_leftover_cache_files(do_it=false, options={})

# Returns true if RemoteResource +rr+ is allowed to access DataProvider +check_dp+
# (which defaults to self). The information for this restriction is maintained
# as a blacklist in the meta data store.
# according to whitelist, blacklist and default value in the meta data store.
def rr_allowed_syncing?(rr = RemoteResource.current_resource, check_dp = self)
rr ||= RemoteResource.current_resource
meta_key_disabled = "rr_no_sync_#{rr.id}"
check_dp.meta[meta_key_disabled].blank?
meta_key = "rr_no_sync_#{rr.id}"
default = check_dp.meta["rr_no_sync_default"] || 'allowed' # default for default is allow sync
policy = ( self.meta[meta_key].presence || default )
return policy.length != 8 # shorter or longer than 'disabled' (either 'allowed' or long legacy sentence)
end

# Works like rr_allowed_syncing? but raise an exception when the
Expand All @@ -1379,11 +1381,17 @@ def rr_allowed_syncing!(server_does_what = "access the files of", rr = RemoteRes

# Returns true if the DataProvider is allowed to copy or move files to the
# other DataProvider +other_dp+ .
# The information for this restriction is maintained
# as a blacklist in the meta data store.
# The information for this restriction is maintained by default value
# along with a white- and blacklist, all stored in the meta data store.
def dp_allows_copy?(other_dp)
meta_key_disabled = "dp_no_copy_#{other_dp.id}"
self.meta[meta_key_disabled].blank?
meta_key = "dp_no_copy_#{other_dp.id}"
# if there is no explicit flag for particular provider
# fall back on the default policy
default = self.meta["dp_no_copy_default"]
return ( self.meta[meta_key].presence || default ) != "disabled"
# hacky equivalent of
# return true if self.meta[meta_key] == 'copy' # yes if whitelisted
# self.meta[meta_key].blank? && default != "disabled" # otherwise by dafault
end

# Works like dp_allows_copy? but raises an exception if the
Expand Down
70 changes: 65 additions & 5 deletions BrainPortal/app/views/data_providers/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,26 @@
#
-%>


<% title 'Data Provider Info' %>

<% has_owner_access = (check_role(:admin_user) || @provider.user_id == current_user.id) %>
<% is_userkey_dp = @provider.is_a?(UserkeyFlatDirSshDataProvider) %>
<% needs_ssh_config = @provider.is_a?(SshDataProvider) || @provider.is_a?(SmartDataProviderInterface) %>

<%
# tribox method creates tristate checkbox for table, to be used with meta data store
# meta_value can have values allowed, disabled and empty (=indetermiate state)
def tribox(t, model, meta_key, meta_value, default_value, cls)
if meta_value.present?
t.boolean_edit_cell("meta[#{meta_key}]", meta_value, "allowed", "disabled", :header => "#{model.name}", :class => 'checkbox_label', :input_options => { class: cls } )
else
t.boolean_edit_cell("meta[#{meta_key}]", default_value, "allowed", "disabled", :header => "<em>#{model.name}</em>".html_safe, :class => 'checkbox_label indeterminate_box_label', :input_options => { class: "#{cls} indeterminate" } )
end
end
%>


<div class="menu_bar">

<% if @provider.is_browsable?(current_user) && @provider.online? %>
Expand Down Expand Up @@ -224,20 +238,43 @@

<%= show_table(@provider, :as => :data_provider, :width => 5, :header => 'Files can be copied or moved to these other Data Providers', :edit_condition => (check_role(:admin_user) || @provider.user_id == current_user.id)) do |t| %>
<% if dps_by_category[:official] %>
<% t.row(:class => 'subheader') { "<strong>Official Storage</strong>".html_safe } %>

<% t.row(:class => 'subheader') do %>
<strong>Mass controls </strong>
<% end %>
<% t.boolean_edit_cell("Unsaved toggle", "", "", "", :header => "Reset old to", :class => 'checkbox_label') do %>
<%#= select_all_checkbox("dp_box", :persistant_name => meta_key, :id => :dp_select_all) %>
<%= select_all_checkbox("dp_box", :id => :dp_select_all) %>
<% end %>
<% default_key = "dp_no_copy_default" %>
<!-- copy to new dataproviders allowed by default -->
<% default_value = @provider.meta[default_key] || "allowed" %>
<% t.boolean_edit_cell("meta[#{default_key}]", default_value, "allowed", "disabled", :header => "Default to", :class => 'checkbox_label') %>
<% t.cell("on all future providers", :no_header => "explanations", :class => "indeterminate_box_label") do %>
&nbsp on new and future providers
<% end %>
<% t.blank_row %>
<% t.row(:class => 'subheader') do %>
<strong>Official Storage </strong>
<% end %>

<% dps_by_category[:official].sort_by(&:name).each do |dp| %>
<% meta_key = "dp_no_copy_#{dp.id}" %>
<% t.boolean_edit_cell("meta[#{meta_key}]", @provider.meta[meta_key].to_s, "", "disabled", :header => "#{dp.name}", :class => 'checkbox_label') %>
<% meta_value = @provider.meta[meta_key] %>
<% tribox(t, dp, meta_key, meta_value, default_value, "dp_box" ) %>
<% end%>

<% end%>

<% t.blank_row %>


<% if dps_by_category[:user] %>
<% t.row(:class => 'subheader') { "<strong>User or Site Storage</strong>".html_safe } %>
<% dps_by_category[:user].sort_by(&:name).each do |dp| %>
<% meta_key = "dp_no_copy_#{dp.id}" %>
<% t.boolean_edit_cell("meta[#{meta_key}]", @provider.meta[meta_key].to_s, "", "disabled", :header => "#{dp.name}", :class => 'checkbox_label') %>
<% meta_value = @provider.meta[meta_key] %>
<% tribox(t, dp, meta_key, meta_value, default_value, "dp_box" ) %>
<% end%>
<% end%>
<% end%>
Expand All @@ -249,11 +286,28 @@
<% if other_rrs.size > 0 %>

<%= show_table(@provider, :as => :data_provider, :width => 5, :header => 'File contents can be accessed by these Servers', :edit_condition => (check_role(:admin_user) || @provider.user_id == current_user.id)) do |t| %>

<% t.row(:class => 'subheader') do %>
<strong>Mass controls </strong>
<% end %>
<% t.boolean_edit_cell("Unsaved toggle", "", "", "", :header => "Reset old to", :class => 'checkbox_label') do %>
<%= select_all_checkbox("rr_box", :id => :rr_select_all) %>
<% end %>
<% default_key = "rr_no_sync_default" %>
<!-- sycn to new Remote Resources allowed by default -->
<% default_value = @provider.meta[default_key] || "allowed" %>
<% t.boolean_edit_cell("meta[#{default_key}]", default_value, "allowed", "disabled", :header => "Default to", :class => 'checkbox_label') %>
<% t.cell("on all future servers", :no_header => "explanations", :class => "indeterminate_box_label") do %>
&nbsp on new and future servers
<% end %>
<% t.blank_row %>

<% if rrs_by_category[:portal] %>
<% t.row(:class => 'subheader') { "<strong>Portals<strong>".html_safe } %>
<% rrs_by_category[:portal].sort_by(&:name).each do |rr| %>
<% meta_key = "rr_no_sync_#{rr.id}" %>
<% t.boolean_edit_cell("meta[#{meta_key}]", @provider.meta[meta_key].to_s, "", "#{rr.name} cannot sync #{@provider.name}", :header => "#{rr.name}", :class => 'checkbox_label') %>
<% meta_value = "disabled" if @provider.meta[meta_key]&.length&.> 7 # to avoid migration, works with old and new value %>
<% tribox(t, rr, meta_key, meta_value, default_value, "rr_box" ) %>
<% end%>
<% end%>

Expand All @@ -263,7 +317,9 @@
<% t.row(:class => 'subheader') { "<strong>Execution Servers<strong>".html_safe } %>
<% rrs_by_category[:bourreau].sort_by(&:name).each do |rr| %>
<% meta_key = "rr_no_sync_#{rr.id}" %>
<% t.boolean_edit_cell("meta[#{meta_key}]", @provider.meta[meta_key].to_s, "", "#{rr.name} cannot sync #{@provider.name}", :header => "#{rr.name}", :class => 'checkbox_label') %>
<% meta_value = @provider.meta[meta_key] %>
<% meta_value = "disabled" if @provider.meta[meta_key]&.length&.> 7 # to avoid migration%>
<% tribox(t, rr, meta_key, meta_value, default_value, "rr_box" ) %>
<% end%>
<% end%>
<% end%>
Expand Down Expand Up @@ -291,3 +347,7 @@
<%= render :partial => "layouts/log_report", :locals => { :log => @provider.getlog, :title => "Data Provider Log" } %>
<% end %>

<% content_for :scripts do %>
<%= javascript_include_tag 'cbrain/data_providers/tribox' %>
<% end %>

2 changes: 2 additions & 0 deletions BrainPortal/public/javascripts/cbrain.js
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,8 @@

$('.' + checkbox_class).each(function(index, element) {
element.checked = header_box.prop('checked');
// todo add artificial event, e.g. to propagage changes with tri-state checkboxes
// smth like element.trigger("code-change")
});
};

Expand Down
57 changes: 57 additions & 0 deletions BrainPortal/public/javascripts/cbrain/data_providers/tribox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// CBRAIN Project
//
// Copyright (C) 2008-2012
// The Royal Institution for the Advancement of Learning
// McGill University
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//

// JS to add indetermitate state to checkboxes with indeterninate style

// indeterminate state on can be set with JS
// all elements with empty value are set as indeterminate
$(".show_table_edit_link").click(
function () {
$(".indeterminate").each(
function () {
$(this).prop("indeterminate", true);
$(this).val(""); // checked indeterminate can still passes value
let prev = $(this).prev();
let val = prev.val();
if (val == "disabled") {
prev.val("");
}
}
)
}
);


$(".indeterminate").click(
function () {
$(this).val('allowed');
let prev = $(this).prev();
prev.val("disabled");
}
)







Loading