diff --git a/BrainPortal/app/controllers/invitations_controller.rb b/BrainPortal/app/controllers/invitations_controller.rb index c2fa818e5..d47752cef 100644 --- a/BrainPortal/app/controllers/invitations_controller.rb +++ b/BrainPortal/app/controllers/invitations_controller.rb @@ -27,6 +27,9 @@ class InvitationsController < ApplicationController before_action :login_required + # for uniformity with NH part group license check should be done before inviting people, e.g. by admins + before_action :custom_license_check, :only => [:create, :create_with_usernames] + # Create an invitation def new #:nodoc: @group = Group.find(params[:group_id]) @@ -45,8 +48,75 @@ def new #:nodoc: render :partial => "new" end - # Send an invitation - def create #:nodoc: + def create_with_usernames # creates and sends invitation based either on email or username (works only for users already in shared projects) + # unlike create can reach non-accessible users (to confirm) + + # better validation than in create method (perhaps to replace one in create), prevent user abusing system by + # instrumenting browser + @group = current_user.viewable_groups.where(:type => 'WorkGroup').find(params[:group_id]) + raise ActiveRecord::RecordNotFound unless @group.can_be_accessed_by?(current_user) + group_id = @group.id + return if current_user.own_group.id == group_id # do not add extra user to the system group + + # The form allows users to invite by emails or usernames, even though + # the parameter is only called :emails + user_specs = (params[:emails].presence.try(:strip) || "").split(/[\s,]+/) + user_specs = user_specs.map(&:presence).compact + + if user_specs.empty? + cb_error "Please specify at least one correct CBRAIN username or email", :redirect => group_path(@group) + end + + # Fetch the users + uids_by_email = current_user.visible_users.where(:email => user_specs).pluck(:id) + uids_by_uname = current_user.visible_users.where(:login => user_specs).pluck(:id) + user_ids = uids_by_email | uids_by_uname + found_users = current_user.visible_users.where(:id => user_ids).to_a + found_specs = user_specs.select do |spec| + found_users.any? { |u| u.login == spec || u.email == spec } + end + + not_found_specs = user_specs - found_specs + + flash_warnings = [] + flash_errors = [] + if not_found_specs.present? + flash_errors.push <<-MESSAGE + We are not able to invite user(s) identified by: #{not_found_specs.join(", ")}. + At the moment users are matched by emails or usernames. + Please confirm with your collaborators which email or username they use in NeuroHub. + MESSAGE + end + + # Which invitations are pending? + already_sent_to = Invitation.where(active: true, user_id: user_ids, group_id: @group.id).pluck(:user_id) + rejected_ids = user_ids & already_sent_to + if rejected_ids.present? + already_logins = User.where(:id => rejected_ids).pluck(:login).join(", ") + flash_warnings.push "Already invited: #{already_logins}" + end + + # List of newly invited users + invited_users = User.find(user_ids - already_sent_to - @group.user_ids) + if invited_users.present? + Invitation.send_out(current_user, @group, invited_users) + flash[:notice] = "Your invitation was successfully sent to #{view_pluralize(invited_users.size,"user")}" + else + flash_errors << "No new users were found to invite." + end + + flash[:warning] = flash_warnings.join "\n" if flash_warnings.present? + flash[:error] = flash_errors.join "\n" if flash_errors.present? + + respond_to do |format| + format.html { redirect_to group_path(@group) } + format.xml { head :ok } + end + end + + + # Send invitations + def create(user_ids = nil) #:nodoc: @group = Group.find(params[:group_id]) user_ids = (params[:user_ids] || []).map(&:to_i) already_sent_to = Invitation.where(sender_id: current_user.id, active: true, user_id: user_ids, group_id: @group.id).all.map(&:user_id) diff --git a/BrainPortal/app/controllers/nh_invitations_controller.rb b/BrainPortal/app/controllers/nh_invitations_controller.rb index 46f45bb73..3d1d6208c 100644 --- a/BrainPortal/app/controllers/nh_invitations_controller.rb +++ b/BrainPortal/app/controllers/nh_invitations_controller.rb @@ -51,7 +51,7 @@ def create #:nodoc: uids_by_email = User.where(:email => user_specs).pluck(:id) uids_by_uname = User.where(:login => user_specs).pluck(:id) user_ids = uids_by_email | uids_by_uname - found_users = User.where(:id => user_ids).to_a + found_users = User.where(:id => user_ids).to_a.uniq found_specs = user_specs.select do |spec| found_users.any? { |u| u.login == spec || u.email == spec } end diff --git a/BrainPortal/app/views/invitations/_new.html.erb b/BrainPortal/app/views/invitations/_new.html.erb index 465f3563b..5fef73537 100644 --- a/BrainPortal/app/views/invitations/_new.html.erb +++ b/BrainPortal/app/views/invitations/_new.html.erb @@ -24,7 +24,21 @@ -%>
<% if @users.count > 0 %> - <%= form_tag invitations_path do -%> +
+ Either type in user logins (usernames) or emails +
+ + <%= form_tag create_with_usernames_invitations_path do %> + <%= hidden_field_tag :group_id, @group.id %> + <%= text_area_tag :emails, "", size: "65x2" %> +
+ <%= submit_tag "Send Invitations" %> or, select users in the form below + <% end %> +
+
+
+
+ <%= form_tag invitations_path do -%> <%= hidden_field_tag :group_id, @group.id %> <%= render :partial => 'groups/users_form', :locals => {:parameter_name => "user_ids", :show_locked => false} %>

diff --git a/BrainPortal/config/routes.rb b/BrainPortal/config/routes.rb index 39051ed11..fd050db8e 100644 --- a/BrainPortal/config/routes.rb +++ b/BrainPortal/config/routes.rb @@ -81,7 +81,11 @@ end end - resources :invitations, :only => [ :new, :create, :update, :destroy ] + resources :invitations, :only => [ :new, :create, :update, :destroy ] do + collection do + post 'create_with_usernames' + end + end resources :bourreaux, :except => [ :edit ] do member do diff --git a/BrainPortal/lib/permission_helpers.rb b/BrainPortal/lib/permission_helpers.rb index 9e8127686..4c8233ba7 100644 --- a/BrainPortal/lib/permission_helpers.rb +++ b/BrainPortal/lib/permission_helpers.rb @@ -81,5 +81,26 @@ def check_if_locked end end end + + def params_group_id + return params[:id] if params[:controller] == 'groups' + params[:group_id] if params[:controller] != 'groups' + end + + def custom_license_check(group_id=nil) # check licenses created by user + gid = group_id | params_group_id + return true if gid.blank? + return true if gid == 'all' + # if unexpected id - let the action method handle the error message + begin + @group = current_user.viewable_groups.find(gid) + rescue ActiveRecord::RecordNotFound + return true + end + if current_user.unsigned_custom_licenses(@group).present? + flash[:error] = "Access to the project #{@group.name} is blocked due to licensing issues. Please consult with the project maintainer or support for details" + license_redirect + end + end end