diff --git a/BrainPortal/app/assets/stylesheets/cbrain.css.erb b/BrainPortal/app/assets/stylesheets/cbrain.css.erb
index bccab7597..c294fc553 100644
--- a/BrainPortal/app/assets/stylesheets/cbrain.css.erb
+++ b/BrainPortal/app/assets/stylesheets/cbrain.css.erb
@@ -2586,11 +2586,13 @@ img {
#data_provider_classes {
z-index: 1111;
- max-width: 60em;
+ width: 60%;
position: absolute;
background-color: white;
border: 0.2em solid #0471B4;
padding: 1em;
+ word-wrap: break-word;
+ white-space: normal;
}
diff --git a/BrainPortal/app/controllers/data_providers_controller.rb b/BrainPortal/app/controllers/data_providers_controller.rb
index b39726684..493439670 100644
--- a/BrainPortal/app/controllers/data_providers_controller.rb
+++ b/BrainPortal/app/controllers/data_providers_controller.rb
@@ -64,6 +64,8 @@ def show #:nodoc:
@provider = DataProvider.find(data_provider_id)
cb_notice "Provider not accessible by current user." unless @provider.can_be_accessed_by?(current_user)
+ @typelist = get_type_list
+
respond_to do |format|
format.html # show.html.erb
format.xml {
@@ -77,19 +79,30 @@ def show #:nodoc:
def new #:nodoc:
provider_group_id = current_assignable_group.id
- @provider = DataProvider.new( :user_id => current_user.id,
+ @provider = DataProvider.new(
+ :user_id => current_user.id,
:group_id => provider_group_id,
:online => true,
:read_only => false
)
- @typelist = get_type_list
+ @unsaved_meta = {}
+ @is_personal = false
+ @typelist = get_type_list
+
+ # Edit/create/show are the same view
+ render :action => :show
end
def create #:nodoc:
@provider = DataProvider.sti_new(data_provider_params)
@provider.user_id ||= current_user.id # disabled field in form DOES NOT send value!
@provider.group_id ||= current_assignable_group.id
+ @unsaved_meta = params[:meta] || {}
+
+ # Fix some attributes
+ @provider.update_attributes(userkey_provider_params) if @provider.is_a?(UserkeyFlatDirSshDataProvider)
+ @provider.update_attributes(s3_provider_params) if @provider.is_a?(S3FlatDataProvider)
if @provider.save
add_meta_data_from_form(@provider, [:must_move, :no_uploads, :no_viewers, :browse_gid])
@@ -103,7 +116,7 @@ def create #:nodoc:
else
@typelist = get_type_list
respond_to do |format|
- format.html { render :action => :new }
+ format.html { render :action => :show }
format.xml { render :xml => @provider.errors, :status => :unprocessable_entity }
format.json { render :json => @provider.errors, :status => :unprocessable_entity }
end
@@ -117,32 +130,40 @@ def new_personal #:nodoc:
:online => true,
:read_only => false,
)
- @groups = current_user.assignable_groups
+ @unsaved_meta = {}
+ @is_personal = true
+ @typelist = get_personal_type_list
+
+ # Edit/create/show are the same view
+ render :action => :show
end
# Can be create by normal user,
# only UserkeyFlatDirSshDataProvider, S3FlatDataProvider, S3MultiLevelDataProvider
def create_personal
- @provider = DataProvider.new(base_provider_params).class_update
- @provider.update_attributes(userkey_provider_params) if @provider.is_a?(UserkeyFlatDirSshDataProvider)
- @provider.update_attributes(s3_provider_params) if @provider.is_a?(S3FlatDataProvider)
-
- authorized_type = [UserkeyFlatDirSshDataProvider, S3FlatDataProvider, S3MultiLevelDataProvider]
- @provider.errors.add(:type, "is not allowed") unless authorized_type.include?(@provider.type)
+ @unsaved_meta = params[:meta] || {}
+ @provider = DataProvider.new(base_provider_params).class_update
# Fix some attributes
@provider.user_id = current_user.id
@provider.group_id = current_user.own_group.id unless
current_user.assignable_group_ids.include?(@provider.group_id)
@provider.online = true
- if ! @provider.save
+ @provider.update_attributes(userkey_provider_params) if @provider.is_a?(UserkeyFlatDirSshDataProvider)
+ @provider.update_attributes(s3_provider_params) if @provider.is_a?(S3FlatDataProvider)
+
+ authorized_type = ["UserkeyFlatDirSshDataProvider", "S3FlatDataProvider", "S3MultiLevelDataProvider"]
+ @provider.errors.add(:type, "is not allowed") unless authorized_type.include?(@provider.type)
+
+ if ! @provider.errors.empty? || ! @provider.save
+ @typelist = get_personal_type_list
@groups = current_user.assignable_groups
respond_to do |format|
- format.html { render :action => :new_personal}
+ format.html { render :action => :show }
format.json { render :json => @provider.errors, :status => :unprocessable_entity }
end
- return
+ return
end
@provider.addlog_context(self, "Created by #{current_user.login}")
@@ -808,8 +829,30 @@ def get_type_list #:nodoc:
grouped_options = data_provider_list.to_a.hashed_partitions { |name| name.constantize.pretty_category_name }
grouped_options.delete(nil) # data providers that can not be on this list return a category name of nil, so we remove them
grouped_options.keys.sort.map { |type| [ type, grouped_options[type].sort ] }
+
+ return grouped_options
end
+ def get_personal_type_list #:nodoc:
+ data_provider_list = [ "FlatDirSshDataProvider" ]
+ data_provider_list = DataProvider.descendants.map(&:name)
+
+ grouped_options = data_provider_list.to_a.hashed_partitions { |name| name.constantize.pretty_category_name }
+ # Keep only Cloud
+ grouped_options = grouped_options.select { |type, values| ["Cloud"].include?(type) }
+ # Remove S3DataProvider
+ grouped_options["Cloud"].reject! { |v| v == S3DataProvider.name } if grouped_options["Cloud"]
+
+ # Add UserkeyFlatDirSshDataProvider group
+ category_of_userkey_dp = UserkeyFlatDirSshDataProvider.pretty_category_name
+ userkey_group = grouped_options.find { |type, _ | type == category_of_userkey_dp } || []
+ userkey_group << UserkeyFlatDirSshDataProvider.name
+ grouped_options[category_of_userkey_dp] = userkey_group
+
+ return grouped_options
+ end
+
+
# A name to store the scope for the browsing page;
# a distinct scope is used for each distinct DP
def browse_scope_name(provider) #:nodoc:
diff --git a/BrainPortal/app/models/s3_flat_data_provider.rb b/BrainPortal/app/models/s3_flat_data_provider.rb
index 7747302ce..10bf53617 100644
--- a/BrainPortal/app/models/s3_flat_data_provider.rb
+++ b/BrainPortal/app/models/s3_flat_data_provider.rb
@@ -53,6 +53,14 @@ class S3FlatDataProvider < DataProvider
validates :cloud_storage_client_identifier, length: { in: 16..128 }
validates :cloud_storage_client_token, length: { in: 20..100 }
+ # Attributes of:
+ # - SshDataProvider attributes (not appllicable to S3)
+ # - Containerized attributes (not applicable to S3)
+ # should be absent for this DP class.
+ validates :remote_user, :remote_host, :remote_port, :remote_dir,
+ :containerized_path,
+ absence: true
+
validates :cloud_storage_client_bucket_name, format: {
with: /\A[A-Za-z0-9][A-Za-z0-9\-.]{1,61}[A-Za-z0-9]\z/, # this is good enough; DP will just crash on bad names
message: "invalid S3 bucket name, for rules see https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-s3-bucket-naming-requirements.html"
diff --git a/BrainPortal/app/models/ssh_data_provider.rb b/BrainPortal/app/models/ssh_data_provider.rb
index 853794dee..ea2616131 100644
--- a/BrainPortal/app/models/ssh_data_provider.rb
+++ b/BrainPortal/app/models/ssh_data_provider.rb
@@ -35,6 +35,17 @@ class SshDataProvider < DataProvider
include SshDataProviderBase
+ # Attributes of:
+ # - S3 attributes (not appllicable to Ssh)
+ # - Containerized attributes (not applicable to Ssh)
+ # should be absent for this DP class.
+ validates :cloud_storage_client_identifier, :cloud_storage_client_token,
+ :cloud_storage_client_bucket_name, :cloud_storage_client_path_start,
+ :cloud_storage_endpoint, :cloud_storage_region,
+ :containerized_path,
+ absence: true
+
+
Revision_info=CbrainFileRevision[__FILE__] #:nodoc:
# This returns the category of the data provider
diff --git a/BrainPortal/app/views/data_providers/_dp_types_explained.html.erb b/BrainPortal/app/views/data_providers/_dp_types_explained.html.erb
index 951970e11..60fad118e 100644
--- a/BrainPortal/app/views/data_providers/_dp_types_explained.html.erb
+++ b/BrainPortal/app/views/data_providers/_dp_types_explained.html.erb
@@ -1,97 +1,101 @@
+
+
+This document describes the different types of Data Providers implemented in CBRAIN.
+
+<% if page_is?('data_providers#new') %>
+
+ Not all of them are useful. In production environments, the recommended type is the
+
EnCbrainSmartDataProvider for official data storage and
FlatDirSshDataProvider
+ for user-specific personal storage.
+
+
+ Many provider types come in three variations:
+
+
+ - Local
+ - TypeLocalDataProviders
+ store their information on the local file system where the CBRAIN service
+ resides; as such it means that the files will not be accessible from
+ other remote components of the CBRAIN installation, for instance
+ Execution Servers located on other hosts or supercomputers. Their
+ advantage is that they are fast to access, and the CBRAIN portal will
+ not have to make a local copy of any of the files to work on them
+ or visualize them.
+
+
+ - Ssh
+ - TypeSshDataProviders
+ store their information on file system located on a remote UNIX machine
+ accessible using a SSH account; a file's content is fetched and cached using
+ SFTP or the rsync command and copied locally whenever any
+ component of CBRAIN (including the portal) need to access it.
+
+
+ - Smart
+ - TypeSmartDataProviders
+ are intelligent in that they will act as either a Local or
+ Ssh variant of the same type. The choice is made by
+ each CBRAIN component (Portal, Execution server) independently. Each
+ component compares the hostname where it runs to the Remote Hostname
+ configured for the DataProvider; if they match, the Smart
+ DataProvider will act as a Local one, bypassing any form
+ of caching. If they don't match, it will act as a Ssh one,
+ therefore transferring files and caching them as needed.
+
+
+
+
+
+ The rest of this document describes the different types available, which
+ differ in
what kind of file structure they use to store the
+ files of the users.
+
+
FlatDir*DataProvider:
+ The provider's files are stored in a flat directory, one
+ level deep, directly specified by the object's
Remote Directory
+ attribute. The file "hello" is this stored in a path like this:
+
/remote_dir/hello
+ Note that for historical reasons, the
SshDataProvider
+ is a synonym for
FlatDirSshDataProvider.
+
+
+
+ EnCbrain*DataProvider: The
+ files are stored in a path uniquely determined by
+ the file's ID. A file named "hello" with ID 41233 will be stored
+ like this:
+
/root_dir/04/12/33/hello
+ Such data providers have the advantage that files can be renamed and
+ reassigned to new owners with minimal modifications on the filesystem's
+ structure. The EnCbrain*DataProviders are the officially recommended
+ data providers for production deployment. The data directory where
+ files are stored are
not meant to be accessed and modified by
+ external means, that means no users are supposed to access
+ the files directly in there.
+
+
+ Vault*DataProvider:
+ The provider's files are stored in a flat directory, two levels
+ deep, directly specified by the object's Remote Directory
+ attribute and the user's login name. The file "hello"
+ of user "myuser" is thus stored into a path like this:
+
/remote_dir/myuser/hello
+ On such data providers, it is not possible to reassign ownership
+ of a file.
+
+
+ IncomingVault*DataProvider: This class behaves like the
+ VaultSshDataProvider, except that it is browsable. When browsing, only
+ the subdirectory named like the login name of the current user will
+ be visible. It is perfect for accessing
+ a jailed Remote Directory for incoming content, where users
+ can upload files to these subdirectories on other channels. A typical
+ setup would also use the Remote Directory as the root for
+ an incoming SFTP or FTP server (this is in fact the reason why this
+ type of provider is named like this).
+<% end %>
-This document describes the different types of Data Providers
-implemented in CBRAIN. Not all of them are useful. In production
-environments, the recommended type is the EnCbrainSmartDataProvider
-for official data storage and FlatDirSshDataProvider for user-specific
-personal storage.
-
-
-Many provider types come in three variations:
-
-
- - Local
- - TypeLocalDataProviders
- store their information on the local file system where the CBRAIN service
- resides; as such it means that the files will not be accessible from
- other remote components of the CBRAIN installation, for instance
- Execution Servers located on other hosts or supercomputers. Their
- advantage is that they are fast to access, and the CBRAIN portal will
- not have to make a local copy of any of the files to work on them
- or visualize them.
-
-
- - Ssh
- - TypeSshDataProviders
- store their information on file system located on a remote UNIX machine
- accessible using a SSH account; a file's content is fetched and cached using
- SFTP or the rsync command and copied locally whenever any
- component of CBRAIN (including the portal) need to access it.
-
-
- - Smart
- - TypeSmartDataProviders
- are intelligent in that they will act as either a Local or
- Ssh variant of the same type. The choice is made by
- each CBRAIN component (Portal, Execution server) independently. Each
- component compares the hostname where it runs to the Remote Hostname
- configured for the DataProvider; if they match, the Smart
- DataProvider will act as a Local one, bypassing any form
- of caching. If they don't match, it will act as a Ssh one,
- therefore transferring files and caching them as needed.
-
-
-
-
-
-The rest of this document describes the different types available, which
-differ in
what kind of file structure they use to store the
-files of the users.
-
-
FlatDir*DataProvider:
-The provider's files are stored in a flat directory, one
-level deep, directly specified by the object's
Remote Directory
-attribute. The file "hello" is this stored in a path like this:
-
/remote_dir/hello
-Note that for historical reasons, the
SshDataProvider
-is a synonym for
FlatDirSshDataProvider.
-
-
-
-EnCbrain*DataProvider: The
-files are stored in a path uniquely determined by
-the file's ID. A file named "hello" with ID 41233 will be stored
-like this:
-
/root_dir/04/12/33/hello
-Such data providers have the advantage that files can be renamed and
-reassigned to new owners with minimal modifications on the filesystem's
-structure. The EnCbrain*DataProviders are the officially recommended
-data providers for production deployment. The data directory where
-files are stored are
not meant to be accessed and modified by
-external means, that means no users are supposed to access
-the files directly in there.
-
-
-Vault*DataProvider:
-The provider's files are stored in a flat directory, two levels
-deep, directly specified by the object's Remote Directory
-attribute and the user's login name. The file "hello"
-of user "myuser" is thus stored into a path like this:
-
/remote_dir/myuser/hello
-On such data providers, it is not possible to reassign ownership
-of a file.
-
-
-IncomingVault*DataProvider: This class behaves like the
-VaultSshDataProvider, except that it is browsable. When browsing, only
-the subdirectory named like the login name of the current user will
-be visible. It is perfect for accessing
-a jailed Remote Directory for incoming content, where users
-can upload files to these subdirectories on other channels. A typical
-setup would also use the Remote Directory as the root for
-an incoming SFTP or FTP server (this is in fact the reason why this
-type of provider is named like this).
-
S3DataProvider: This class connects to Amazon's S3
cloud storage service. The files will be stored in a bucket named
"gbrain_{name}" where name is the name of the Data Provider.
@@ -114,16 +118,21 @@ acts like a FlatDataProvider.
-SingSquashfsDataProvider This class connects to a set of
-one or several squashfs files (all named with .squashfs extensions) through
-a Singularity container handler. The requirements are:
-
- - that all the squashfs files are in the Physical Data Location,
-
- the Singularity image is also there and named <%= SingSquashfsDataProvider::SINGULARITY_IMAGE_BASENAME %>,
-
- that this image contains a basic Linux system with at least rsync installed in it,
-
- and that the path to the data root inside the container must be provided in the Containerized Data Path under the Containerized Storage Configuration section.
-
-Note that this DP is already 'smart' in that if the
Remote Host
-configured for it matches the current host, it will not perform its
-data operation through a SSH master.
+<% if page_is?('data_providers#new') %>
+
+
SingSquashfsDataProvider This class connects to a set of
+ one or several squashfs files (all named with
.squashfs extensions) through
+ a Singularity container handler. The requirements are:
+
+ - that all the squashfs files are in the Physical Data Location,
+
- the Singularity image is also there and named <%= SingSquashfsDataProvider::SINGULARITY_IMAGE_BASENAME %>,
+
- that this image contains a basic Linux system with at least rsync installed in it,
+
- and that the path to the data root inside the container must be provided in the Containerized Data Path under the Containerized Storage Configuration section.
+
+ Note that this DP is already 'smart' in that if the
Remote Host
+ configured for it matches the current host, it will not perform its
+ data operation through a SSH master.
+
+<% end %>
+
diff --git a/BrainPortal/app/views/data_providers/new.html.erb b/BrainPortal/app/views/data_providers/new.html.erb
deleted file mode 100644
index c3aec765d..000000000
--- a/BrainPortal/app/views/data_providers/new.html.erb
+++ /dev/null
@@ -1,229 +0,0 @@
-
-<%-
-#
-# 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
- <%= show_table(@provider, :as => :data_provider, :edit_condition => has_owner_access) do |t| %>
-
- <% t.edit_cell(:name) do |f| %>
- <%= f.text_field :name %>
- <% end %>
+<%= show_table_context(@provider, :url => url) do |cf| %>
- <% t.edit_cell(:description, :content => full_description(@provider.description)) do |f| %>
- <%= f.text_area :description, :rows => 10, :cols => 40 %>
- <% end %>
+
+ <%= show_table(@provider, :form_helper => cf, :as => :data_provider, :edit_condition => has_owner_access) do |t| %>
- <% if has_owner_access %>
- <% t.attribute_cell(:type) %>
- <% else %>
- <% t.empty_cell %>
- <% end %>
-
- <% t.edit_cell(:online, :content => (@provider.online ? "Online" : "Offline")) do |f| %>
- <%= f.select :online, [["Online", true], ["Offline", false]] %>
- <% end %>
-
- <% t.edit_cell(:user_id, :header => "Owner", :content => link_to_user_with_tooltip(@provider.user), :disabled => ! current_user.has_role?(:admin_user) ) do %>
- <%= user_select("data_provider[user_id]", { :selector => @provider } ) %>
- <% end %>
-
- <% t.edit_cell(:read_only, :content => (@provider.read_only ? "Read Only" : "Read/Write"), :header => "Mode") do |f| %>
- <%= f.select :read_only, [["Read/Write", false], ["Read Only", true]] %>
- <% end %>
+ <% t.edit_cell(:name) do |f| %>
+ <%= f.text_field :name %>
+ <% end %>
- <% t.edit_cell(:group_id, :header => "Project", :content => link_to_group_if_accessible(@provider.group) ) do %>
- <%= group_select("data_provider[group_id]", { :selector => @provider }) %>
- <% end %>
+ <% t.edit_cell(:description, :content => full_description(@provider.description)) do |f| %>
+ <%= f.text_area :description, :rows => 10, :cols => 40 %>
+ <% end %>
- <% t.edit_cell(:not_syncable, :content => (@provider.not_syncable ? "NOT syncable" : "Fully syncable"), :header => "Syncability") do |f| %>
- <%= f.select :not_syncable, [["Fully syncable", false], ["NOT syncable", true]] %>
- <% end %>
+ <% if is_new_record || has_owner_access %>
+ <% t.edit_cell(:type, :content => @provider.type) do |f| %>
+ <%= f.select :type, grouped_options_for_select(@typelist, @provider.type) %>
+ <% if !is_normal_user %>
+
<%= show_hide_toggle "(Data Provider Type Information)", "#data_provider_classes", :class => 'action_link' %>
+
+
+
+ <%= render :partial => 'dp_types_explained' %>
+
+ <% end %>
+ <% end %>
+ <% else %>
+ <% t.empty_cell %>
+ <% end %>
- <% if current_user.has_role?(:admin_user) %>
- <% t.cell("Revision Info (DataProvider)", :show_width => 2) { DataProvider.revision_info.format() } %>
- <% t.cell("Revision Info (#{@provider.type})", :show_width => 2) { @provider.revision_info.format() } %>
- <% end %>
+ <% t.edit_cell(:online, :content => (@provider.online ? "Online" : "Offline")) do |f| %>
+ <%= f.select :online, [["Online", true], ["Offline", false]] %>
+ <% end %>
- <% if ! is_userkey_dp %>
- <% t.edit_cell(:time_zone, :content => (@provider.time_zone || "(Unset)"), :show_width => 2 ) do |f| %>
- <%= f.select :time_zone, time_zone_options_for_select(@provider.time_zone, /canada/i), :include_blank => true %>
+ <% t.edit_cell(:user_id, :header => "Owner", :content => link_to_user_with_tooltip(@provider.user), :disabled => ! current_user.has_role?(:admin_user) ) do %>
+ <%= user_select("data_provider[user_id]", { :selector => @provider } ) %>
<% end %>
- <% end %>
- <% if has_owner_access %>
- <% t.edit_cell(:remote_dir, :header => "Physical Data Location", :show_width => 2) do |f| %>
- <%= f.text_field :remote_dir, :size => 80 %>
+ <% t.edit_cell(:read_only, :content => (@provider.read_only ? "Read Only" : "Read/Write"), :header => "Mode") do |f| %>
+ <%= f.select :read_only, [["Read/Write", false], ["Read Only", true]] %>
<% end %>
- <% end %>
- <% if current_user.has_role?(:admin_user) %>
- <% joint_licenses = @provider.license_agreements.join("\n") %>
- <% licenses = @provider.license_agreements.count == 0 ? "(None)": @provider.license_agreements.join("\n") %>
- <% t.edit_cell(:license_agreements, :content => licenses, :show_width => 2) do |f| %>
- <%= f.text_area :license_agreements, :value => joint_licenses, :content => joint_licenses, :rows => 5, :cols => 40 %>
-
Enter one agreement name per line. Note that only alphanumeric characters, underscores (_) and dashes (-) are accepted.
- <% end %>
- <% else %>
- <% t.empty_cell %>
- <% end %>
+ <% t.edit_cell(:group_id, :header => "Project", :content => link_to_group_if_accessible(@provider.group) ) do %>
+ <%= group_select("data_provider[group_id]", { :selector => @provider }) %>
+ <% end %>
- <% end %>
+ <% t.edit_cell(:not_syncable, :content => (@provider.not_syncable ? "NOT syncable" : "Fully syncable"), :header => "Syncability") do |f| %>
+ <%= f.select :not_syncable, [["Fully syncable", false], ["NOT syncable", true]] %>
+ <% end %>
- <% if has_owner_access && needs_ssh_config %>
- <%= show_table(@provider, :as => :data_provider, :header => "SSH parameters", :edit_condition => true) do |t| %>
- <% t.edit_cell(:remote_host, :show_width => 2) do |f| %>
- <%= f.text_field :remote_host, :size => 40 %>
+ <% if current_user.has_role?(:admin_user) %>
+ <% t.cell("Revision Info (DataProvider)", :show_width => 2) { DataProvider.revision_info.format() } %>
+ <% t.cell("Revision Info (#{@provider.type})", :show_width => 2) { @provider.revision_info.format() } %>
<% end %>
- <% if check_role(:admin_user) %>
- <% t.edit_cell(:alternate_host, :show_width => 2, :header => "Alternate hostname(s)") do |f| %>
- <%= f.text_field :alternate_host, :size => 100 %>
-
Comma-separated list of alternate hostnames; hostname1,hostname2,hostname3,...
+
+ <% if ! is_userkey_dp %>
+ <% t.edit_cell(:time_zone, :content => (@provider.time_zone || "(Unset)"), :show_width => 2 ) do |f| %>
+ <%= f.select :time_zone, time_zone_options_for_select(@provider.time_zone, /canada/i), :include_blank => true %>
<% end %>
<% end %>
- <% t.edit_cell(:remote_user) do |f| %>
- <%= f.text_field :remote_user, :size => 40 %>
- <% end %>
- <% t.edit_cell(:remote_port) do |f| %>
- <%= f.text_field :remote_port, :size => 6 %>
+
+ <% if is_new_record || has_owner_access %>
+ <% t.edit_cell(:remote_dir, :header => "Physical Data Location", :show_width => 2) do |f| %>
+ <%= f.text_field :remote_dir, :size => 80 %>
+ <% end %>
<% end %>
- <% end %>
- <% end %>
- <% if @provider.is_a?(SingSquashfsDataProvider) || @provider.is_a?(SingBindmountDataProvider) %>
- <%= show_table(@provider, :as => :data_provider, :header => "Containerized Storage Configuration", :edit_condition => true) do |t| %>
- <% t.edit_cell(:containerized_path, :header => 'Containerized Data Path', :show_width => 2) do %>
- <%= text_field_tag "data_provider[containerized_path]", @provider.containerized_path, :size => 80 %>
+ <% if current_user.has_role?(:admin_user) %>
+ <% joint_licenses = @provider.license_agreements.join("\n") %>
+ <% licenses = @provider.license_agreements.count == 0 ? "(None)": @provider.license_agreements.join("\n") %>
+ <% t.edit_cell(:license_agreements, :content => licenses, :show_width => 2) do |f| %>
+ <%= f.text_area :license_agreements, :value => joint_licenses, :content => joint_licenses, :rows => 5, :cols => 40 %>
+
Enter one agreement name per line. Note that only alphanumeric characters, underscores (_) and dashes (-) are accepted.
+ <% end %>
+ <% else %>
+ <% t.empty_cell %>
<% end %>
+
<% end %>
- <% end %>
- <% if @provider.is_a?(S3DataProvider) || @provider.is_a?(S3FlatDataProvider) %>
- <%= show_table(@provider, :as => :data_provider, :header => "Cloud Storage Configuration", :edit_condition => true) do |t| %>
- <% t.edit_cell(:cloud_storage_client_identifier, :header => 'Client Identifier', :show_width => 2) do |f| %>
- <%= f.text_field :cloud_storage_client_identifier, :size => 40, :autocomplete => 'off' %>
- <% end %>
- <% t.edit_cell(:cloud_storage_client_token, :content => '****************', :header => 'Client Token', :show_width => 2) do |f| %>
- <%= f.password_field :cloud_storage_client_token, :size => 80, :autocomplete => 'off' %>
- <% end %>
- <% t.edit_cell(:cloud_storage_client_bucket_name, :header => 'Client Bucket Name', :show_width => 2) do %>
- <%= text_field_tag "data_provider[cloud_storage_client_bucket_name]", @provider.cloud_storage_client_bucket_name, :size => 80 %>
- <% end %>
- <% t.edit_cell(:cloud_storage_client_path_start, :header => 'Client Starting Path', :show_width => 2) do %>
- <%= text_field_tag "data_provider[cloud_storage_client_path_start]", @provider.cloud_storage_client_path_start, :size => 80 %>
- <% end %>
- <% t.edit_cell(:cloud_storage_endpoint, :header => 'Endpoint', :show_width => 2) do %>
- <%= text_field_tag "data_provider[cloud_storage_endpoint]", @provider.cloud_storage_endpoint, :size => 80 %>
- <% end %>
- <% t.edit_cell(:cloud_storage_region, :header => 'Region', :show_width => 2) do %>
- <%= text_field_tag "data_provider[cloud_storage_region]", @provider.cloud_storage_region, :size => 80 %>
+
+
+ <% if is_new_record || (has_owner_access && needs_ssh_config) %>
+ <%= show_table(@provider, :form_helper => cf, :as => :data_provider, :header => "SSH parameters", :edit_condition => true) do |t| %>
+
+ <% t.edit_cell(:remote_host, :show_width => 2) do |f| %>
+ <%= f.text_field :remote_host, :size => 40 %>
+ <% end %>
+
+ <% if check_role(:admin_user) %>
+ <% t.edit_cell(:alternate_host, :show_width => 2, :header => "Alternate hostname(s)") do |f| %>
+ <%= f.text_field :alternate_host, :size => 100 %>
+
Comma-separated list of alternate hostnames; hostname1,hostname2,hostname3,...
+ <% end %>
+ <% end %>
+
+ <% t.edit_cell(:remote_user) do |f| %>
+ <%= f.text_field :remote_user, :size => 40 %>
+ <% end %>
+
+ <% t.edit_cell(:remote_port) do |f| %>
+ <%= f.text_field :remote_port, :size => 6 %>
+ <% end %>
+
<% end %>
<% end %>
- <% end %>
- <% if @provider.is_a?(DataladDataProvider) %>
- <%= show_table(@provider, :as => :data_provider, :header => "Datalad Configuration", :edit_condition => true) do |t| %>
- <% t.edit_cell(:datalad_repository_url, :header => 'Datalad Repository URL', :show_width => 2) do |f| %>
- <%= f.text_field :datalad_repository_url %>
- <% end %>
- <% t.edit_cell(:datalad_relative_path, :header => 'Datalad Relative Path', :show_width => 2) do |f| %>
- <%= f.text_field :datalad_relative_path %>
+
+ <% if ( !@is_personal && is_new_record || (@provider.is_a?(SingSquashfsDataProvider) || @provider.is_a?(SingBindmountDataProvider))) %>
+
+ <%= show_table(@provider, :form_helper => cf, :as => :data_provider, :header => "Containerized Storage Configuration", :edit_condition => true) do |t| %>
+ <% t.edit_cell(:containerized_path, :header => 'Containerized Data Path', :show_width => 2) do %>
+ <%= text_field_tag "data_provider[containerized_path]", @provider.containerized_path, :size => 80 %>
+ <% end %>
<% end %>
+
<% end %>
- <% end %>
+
+ <% if @provider.is_a?(S3DataProvider) || @provider.is_a?(S3FlatDataProvider) || (is_new_record && @typelist.include?("Cloud")) %>
- <%= show_table(@provider, :as => :data_provider, :header => "Other Properties", :edit_condition => (check_role(:admin_user) || @provider.user_id == current_user.id)) do |t| %>
+ <%= show_table(@provider, :form_helper => cf, :as => :data_provider, :header => "Cloud Storage Configuration", :edit_condition => true) do |t| %>
- <% t.boolean_edit_cell("meta[no_uploads]", @provider.meta["no_uploads"], "on", "", :header => "Cannot be used for uploading files in the file manager") %>
+ <% t.edit_cell(:cloud_storage_client_identifier, :header => 'Client Identifier', :show_width => 2) do |f| %>
+ <%= f.text_field :cloud_storage_client_identifier, :size => 40, :autocomplete => 'off' %>
+ <% end %>
- <% t.boolean_edit_cell("meta[no_viewers]", @provider.meta["no_viewers"], "on", "", :header => "Files cannot be viewed in the file manager") %>
+ <% t.edit_cell(:cloud_storage_client_token, :content => '****************', :header => 'Client Token', :show_width => 2) do |f| %>
+ <%= f.password_field :cloud_storage_client_token, :size => 80, :autocomplete => 'off' %>
+ <% end %>
- <% if @provider.is_browsable? %>
+ <% t.edit_cell(:cloud_storage_client_bucket_name, :header => 'Client Bucket Name' + (is_new_record ? '' : ' (Only needed for S3FlatDataProvider)'), :show_width => 2) do |f| %>
+ <%= f.text_field :cloud_storage_client_bucket_name, :size => 80 %>
+ <% end %>
- <% t.boolean_edit_cell("meta[must_move]", @provider.meta["must_move"], "on", "", :header => "Files must be copied/moved upon registration") %>
+ <% t.edit_cell(:cloud_storage_client_path_start, :header => 'Client Starting Path' + (is_new_record ? '' : ' (Only needed for S3FlatDataProvider)'), :show_width => 2) do |f| %>
+ <%= f.text_field :cloud_storage_client_path_start, :size => 80 %>
+ <% end %>
+
+ <% t.edit_cell(:cloud_storage_endpoint, :header => 'Endpoint' + (is_new_record ? '' : ' (Only needed for S3FlatDataProvider)'), :show_width => 2) do |f| %>
+ <%= f.text_field :cloud_storage_endpoint, :size => 80 %>
+ <% end %>
+
+ <% t.edit_cell(:cloud_storage_region, :header => 'Region' + (is_new_record ? '' : ' (Only needed for S3FlatDataProvider)'), :show_width => 2) do |f| %>
+ <%= f.text_field :cloud_storage_region, :size => 80 %>
+ <% end %>
- <% t.edit_cell("meta[browse_gid]",
- :header => "Files can be browsed only by members of this project",
- :content => @provider.meta[:browse_gid].present? ? link_to_group_if_accessible(@provider.meta[:browse_gid]) : '(Any Users)',
- :show_width => 2
- ) do %>
- <%= group_select 'meta[browse_gid]', { :selector => @provider.meta[:browse_gid] }, { :include_blank => "(Any Users)" } %>
<% end %>
+ <% end %>
+
+
+ <% if @provider.is_a?(DataladDataProvider) || (is_new_record && @typelist.include?("DataladProvider")) %>
+
+ <%= show_table(@provider, :form_helper => cf, :as => :data_provider, :header => "Datalad Configuration", :edit_condition => true) do |t| %>
+ <% t.edit_cell(:datalad_repository_url, :header => 'Datalad Repository URL', :show_width => 2) do |f| %>
+ <%= f.text_field :datalad_repository_url %>
+ <% end %>
+
+ <% t.edit_cell(:datalad_relative_path, :header => 'Datalad Relative Path', :show_width => 2) do |f| %>
+ <%= f.text_field :datalad_relative_path %>
+ <% end %>
+
+ <% end %>
<% end %>
- <% end %>
+
+ <% if !@is_personal %>
+ <%= show_table(@provider, :form_helper => cf, :as => :data_provider, :header => "Other Properties", :edit_condition => (check_role(:admin_user) || @provider.user_id == current_user.id)) do |t| %>
+ <% t.boolean_edit_cell("meta[no_uploads]", is_new_record ? @unsaved_meta[:no_uploads] || false : @provider.meta[:no_uploads], "on", "", :header => "Cannot be used for uploading files in the file manager") %>
+ <% t.boolean_edit_cell("meta[no_viewers]", is_new_record ? @unsaved_meta[:no_viewers] || false : @provider.meta[:no_viewers], "on", "", :header => "Files cannot be viewed in the file manager") %>
- <% other_dps = DataProvider.find_all_accessible_by_user(current_user).reject { |dp| dp.id == @provider.id } %>
- <% dps_by_category = other_dps.to_a.hashed_partitions { |dp| dp.is_browsable? ? :user : :official } %>
+ <% if is_new_record || @provider.is_browsable? %>
- <% if other_dps.size > 0 %>
+ <% t.boolean_edit_cell("meta[must_move]", is_new_record ? @unsaved_meta[:must_move] || false : @provider.meta[:must_move], "on", "", :header => "Files must be copied/moved upon registration") %>
- <%= 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') { "
Official Storage".html_safe } %>
- <% 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') %>
- <% end%>
- <% end%>
+ <% browse_gid = !is_new_record ? @provider.meta[:browse_gid].present? : (@unsaved_meta && @unsaved_meta[:browse_gid].present?) %>
+ <% t.edit_cell("meta[browse_gid]",
+ :header => "Files can be browsed only by members of this project",
+ :content => !is_new_record && browse_gid ? link_to_group_if_accessible(@provider.meta[:browse_gid]) : '(Any Users)',
+ :show_width => 2
+ ) do %>
+ <%= group_select 'meta[browse_gid]', { :selector => (is_new_record ? @unsaved_meta[:browse_gid] : @provider.meta[:browse_gid]) }, { :include_blank => "(Any Users)" } %>
+ <% end %>
- <% t.blank_row %>
+ <% end %>
+ <% end %>
- <% if dps_by_category[:user] %>
- <% t.row(:class => 'subheader') { "
User or Site Storage".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') %>
+
+ <% other_dps = DataProvider.find_all_accessible_by_user(current_user).reject { |dp| dp.id == @provider.id } %>
+ <% dps_by_category = other_dps.to_a.hashed_partitions { |dp| dp.is_browsable? ? :user : :official } %>
+
+ <% if other_dps.size > 0 %>
+
+ <%= show_table(@provider, :form_helper => cf, :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') { "
Official Storage".html_safe } %>
+ <% dps_by_category[:official].sort_by(&:name).each do |dp| %>
+ <% meta_key = "dp_no_copy_#{dp.id}" %>
+ <% t.boolean_edit_cell("meta[#{meta_key}]", is_new_record ? @unsaved_meta[meta_key] || false : @provider.meta[meta_key].to_s, "", "disabled", :header => "#{dp.name}", :class => 'checkbox_label') %>
+ <% end%>
+ <% end%>
+
+ <% t.blank_row %>
+
+ <% if dps_by_category[:user] %>
+ <% t.row(:class => 'subheader') { "
User or Site Storage".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}]", is_new_record ? @unsaved_meta[meta_key] || false : @provider.meta[meta_key].to_s, "", "disabled", :header => "#{dp.name}", :class => 'checkbox_label') %>
+ <% end%>
+ <% end%>
<% end%>
<% end%>
+
<% end%>
- <% end%>
- <% other_rrs = RemoteResource.find_all_accessible_by_user(current_user) %>
- <% rrs_by_category = other_rrs.to_a.hashed_partitions { |rr| rr.is_a?(Bourreau) ? :bourreau : :portal } %>
+
+ <% other_rrs = RemoteResource.find_all_accessible_by_user(current_user) %>
+ <% rrs_by_category = other_rrs.to_a.hashed_partitions { |rr| rr.is_a?(Bourreau) ? :bourreau : :portal } %>
- <% if other_rrs.size > 0 %>
+ <% 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| %>
- <% if rrs_by_category[:portal] %>
- <% t.row(:class => 'subheader') { "
Portals".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') %>
+ <%= show_table(@provider, :form_helper => cf, :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| %>
+ <% if rrs_by_category[:portal] %>
+ <% t.row(:class => 'subheader') { "Portals".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}]", is_new_record ? @unsaved_meta[meta_key].to_s : @provider.meta[meta_key].to_s, "", "#{rr.name} cannot sync #{@provider.name}", :header => "#{rr.name}", :class => 'checkbox_label') %>
+ <% end%>
<% end%>
- <% end%>
- <% t.blank_row %>
+ <% t.blank_row %>
- <% if rrs_by_category[:bourreau] %>
- <% t.row(:class => 'subheader') { "Execution Servers".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') %>
+ <% if rrs_by_category[:bourreau] %>
+ <% t.row(:class => 'subheader') { "Execution Servers".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}]", is_new_record ? @unsaved_meta[meta_key].to_s : @provider.meta[meta_key].to_s, "", "#{rr.name} cannot sync #{@provider.name}", :header => "#{rr.name}", :class => 'checkbox_label') %>
+ <% end%>
<% end%>
<% end%>
<% end%>
- <% end%>
+ <% end %>
<% if has_owner_access %>
- <% if is_userkey_dp %>
+ <% if include_personal_ssh %>
<%= render :partial => 'show_user_key' %>
- <% elsif needs_ssh_config %>
-
diff --git a/BrainPortal/spec/controllers/data_providers_controller_spec.rb b/BrainPortal/spec/controllers/data_providers_controller_spec.rb
index 4897be9f4..dad0ad97d 100644
--- a/BrainPortal/spec/controllers/data_providers_controller_spec.rb
+++ b/BrainPortal/spec/controllers/data_providers_controller_spec.rb
@@ -58,9 +58,9 @@
expect(controller).to receive(:get_type_list)
get :new
end
- it "should render the new page" do
+ it "should render the show page" do
get :new
- expect(response).to render_template(:new)
+ expect(response).to render_template(:show)
end
end
describe "create" do
@@ -96,9 +96,9 @@
expect(controller).not_to receive(:add_meta_data_from_form)
post :create, :xhr => true
end
- it "should render new page again" do
+ it "should render show page again" do
post :create, :xhr => true
- expect(response).to render_template(:new)
+ expect(response).to render_template(:show)
end
end
end