module Users class InvitationsController < Devise::InvitationsController include InputSanitizeHelper include UsersGenerator prepend_before_action :check_captcha, only: [:update] before_action :check_invite_users_permission, only: :invite_users before_action :update_sanitized_params, only: :update def update # Instantialize a new team with the provided name @team = Team.new @team.name = params[:team][:name] super do |user| if user.errors.empty? @team.created_by = user @team.save UserTeam.create( user: user, team: @team, role: 'admin' ) end end end def accept_resource unless @team.valid? # Find the user being invited resource = User.find_by_invitation_token( update_resource_params[:invitation_token], false ) # Check if user's data (passwords etc.) is valid resource.assign_attributes( update_resource_params.except(:invitation_token) ) resource.valid? # Call validation to generate errors # In any case, add the team name error resource.errors.add(:base, @team.errors.to_a.first) return resource end super end def invite_users @invite_results = [] @too_many_emails = false cntr = 0 @emails.each do |email| cntr += 1 if cntr > Constants::INVITE_USERS_LIMIT @too_many_emails = true break end password = generate_user_password # Check if user already exists user = nil user = User.find_by_email(email) if User.exists?(email: email) result = { email: email } if user.present? result[:status] = :user_exists result[:user] = user else # Validate the user data error = !(Constants::BASIC_EMAIL_REGEX === email) error = validate_user(email, email, password).count > 0 unless error if !error user = User.invite!( full_name: email, email: email, initials: email.upcase[0..1], skip_invitation: true ) user.update(invited_by: @user) result[:status] = :user_created result[:user] = user # Sending email invitation is done in background job to prevent # issues with email delivery. Also invite method must be call # with :skip_invitation attribute set to true - see above. user.delay.deliver_invitation else # Return invalid status result[:status] = :user_invalid end end if @team.present? && result[:status] != :user_invalid if UserTeam.exists?(user: user, team: @team) user_team = UserTeam.where(user: user, team: @team).first result[:status] = :user_exists_and_in_team else # Also generate user team relation user_team = UserTeam.new( user: user, team: @team, role: @role ) user_team.save generate_notification( @user, user, user_team.role_str, user_team.team ) if result[:status] == :user_exists && !user.confirmed? result[:status] = :user_exists_unconfirmed_invited_to_team elsif result[:status] == :user_exists result[:status] = :user_exists_invited_to_team else result[:status] = :user_created_invited_to_team end end result[:user_team] = user_team end @invite_results << result end respond_to do |format| format.json do render json: { html: render_to_string( partial: 'shared/invite_users_modal_results.html.erb' ) } end end end private def update_sanitized_params # Solution for Devise < 4.0.0 devise_parameter_sanitizer.permit(:sign_up, keys: [:full_name]) end def check_captcha if Rails.configuration.x.enable_recaptcha unless verify_recaptcha self.resource = resource_class.new resource.invitation_token = update_resource_params[:invitation_token] respond_with_navigational(resource) { render :edit } end end end def generate_notification(user, target_user, role, team) title = I18n.t('notifications.assign_user_to_team', assigned_user: target_user.name, role: role, team: team.name, assigned_by_user: user.name) message = "#{I18n.t('search.index.team')} #{team.name}" notification = Notification.create( type_of: :assignment, title: sanitize_input(title), message: sanitize_input(message) ) if target_user.assignments_notification UserNotification.create(notification: notification, user: target_user) end end def check_invite_users_permission @user = current_user @emails = params[:emails].map(&:downcase) @team = Team.find_by_id(params['teamId']) @role = params['role'] render_403 if @emails && @emails.empty? render_403 if @team && !is_admin_of_team(@team) render_403 if @role && !UserTeam.roles.keys.include?(@role) end end end