forked from External/greenlight
		
	GRN2-260: Added the ability to merge user accounts (#938)
* Added the ability to merge user accounts * Styling fixes
This commit is contained in:
		| @@ -41,6 +41,49 @@ $(document).on('turbolinks:load', function(){ | |||||||
|  |  | ||||||
|         updateTabParams(this.id) |         updateTabParams(this.id) | ||||||
|       }) |       }) | ||||||
|  |  | ||||||
|  |       $('.selectpicker').selectpicker({ | ||||||
|  |         liveSearchPlaceholder: getLocalizedString('javascript.search.start') | ||||||
|  |       }); | ||||||
|  |       // Fixes turbolinks issue with bootstrap select | ||||||
|  |       $(window).trigger('load.bs.select.data-api'); | ||||||
|  |        | ||||||
|  |       // Display merge accounts modal with correct info | ||||||
|  |       $(".merge-user").click(function() { | ||||||
|  |         // Update the path of save button | ||||||
|  |         $("#merge-save-access").attr("data-path", $(this).data("path")) | ||||||
|  |  | ||||||
|  |         let userInfo = $(this).data("info") | ||||||
|  |  | ||||||
|  |         $("#merge-to").html("<span>" + userInfo.name + "</span>" + "<span class='text-muted d-block'>" + userInfo.email + "</span>" + "<span class='text-muted d-block'>" + userInfo.uid + "</span>") | ||||||
|  |   | ||||||
|  |       }) | ||||||
|  |  | ||||||
|  |       $("#mergeUserModal").on("show.bs.modal", function() { | ||||||
|  |         $(".selectpicker").selectpicker('val','') | ||||||
|  |       }) | ||||||
|  |    | ||||||
|  |       $(".bootstrap-select").on("click", function() { | ||||||
|  |         $(".bs-searchbox").siblings().hide() | ||||||
|  |       }) | ||||||
|  |    | ||||||
|  |       $(".bs-searchbox input").on("input", function() { | ||||||
|  |         if ($(".bs-searchbox input").val() == '' || $(".bs-searchbox input").val().length < 3) { | ||||||
|  |           $(".bs-searchbox").siblings().hide() | ||||||
|  |         } else { | ||||||
|  |           $(".bs-searchbox").siblings().show() | ||||||
|  |         } | ||||||
|  |       }) | ||||||
|  |  | ||||||
|  |       // User selects an option from the Room Access dropdown | ||||||
|  |       $(".bootstrap-select").on("changed.bs.select", function(){ | ||||||
|  |         // Get the uid of the selected user | ||||||
|  |         let user = $(".selectpicker").selectpicker('val') | ||||||
|  |         if (user != "") { | ||||||
|  |           userInfo = JSON.parse(user) | ||||||
|  |           $("#merge-from").html("<span>" + userInfo.name + "</span>" + "<span class='text-muted d-block'>" + userInfo.email + "</span>" + "<span id='from-uid' class='text-muted d-block'>" + userInfo.uid + "</span>") | ||||||
|  |         } | ||||||
|  |       }) | ||||||
|     } |     } | ||||||
|     else if(action == "site_settings"){ |     else if(action == "site_settings"){ | ||||||
|       loadColourSelectors() |       loadColourSelectors() | ||||||
| @@ -79,6 +122,11 @@ function changeBrandingImage(path) { | |||||||
|   $.post(path, {value: url}) |   $.post(path, {value: url}) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function mergeUsers() { | ||||||
|  |   let userToMerge = $("#from-uid").text() | ||||||
|  |   $.post($("#merge-save-access").data("path"), {merge: userToMerge}) | ||||||
|  | } | ||||||
|  |  | ||||||
| // Filters by role | // Filters by role | ||||||
| function filterRole(role) { | function filterRole(role) { | ||||||
|   var search = new URL(location.href).searchParams.get('search') |   var search = new URL(location.href).searchParams.get('search') | ||||||
|   | |||||||
| @@ -69,7 +69,7 @@ $(document).on('turbolinks:load', function(){ | |||||||
|     }) |     }) | ||||||
|  |  | ||||||
|     $('.selectpicker').selectpicker({ |     $('.selectpicker').selectpicker({ | ||||||
|       liveSearchPlaceholder: "Start searching..." |       liveSearchPlaceholder: getLocalizedString('javascript.search.start') | ||||||
|     }); |     }); | ||||||
|     // Fixes turbolinks issue with bootstrap select |     // Fixes turbolinks issue with bootstrap select | ||||||
|     $(window).trigger('load.bs.select.data-api'); |     $(window).trigger('load.bs.select.data-api'); | ||||||
|   | |||||||
| @@ -88,4 +88,12 @@ | |||||||
|   &:hover { |   &:hover { | ||||||
|     cursor: pointer; |     cursor: pointer; | ||||||
|   } |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #merge-account-arrow { | ||||||
|  |   position: absolute; | ||||||
|  |   top: 47%; | ||||||
|  |   right: 47%; | ||||||
|  |   z-index: 999; | ||||||
|  |   background: white; | ||||||
| } | } | ||||||
| @@ -24,7 +24,7 @@ class AdminsController < ApplicationController | |||||||
|   include Rolify |   include Rolify | ||||||
|   include Populator |   include Populator | ||||||
|  |  | ||||||
|   manage_users = [:edit_user, :promote, :demote, :ban_user, :unban_user, :approve, :reset] |   manage_users = [:edit_user, :promote, :demote, :ban_user, :unban_user, :approve, :reset, :merge_user] | ||||||
|   manage_deleted_users = [:undelete] |   manage_deleted_users = [:undelete] | ||||||
|   authorize_resource class: false |   authorize_resource class: false | ||||||
|   before_action :find_user, only: manage_users |   before_action :find_user, only: manage_users | ||||||
| @@ -41,6 +41,8 @@ class AdminsController < ApplicationController | |||||||
|     @role = params[:role] ? Role.find_by(name: params[:role], provider: @user_domain) : nil |     @role = params[:role] ? Role.find_by(name: params[:role], provider: @user_domain) : nil | ||||||
|     @tab = params[:tab] || "active" |     @tab = params[:tab] || "active" | ||||||
|  |  | ||||||
|  |     @user_list = merge_user_list | ||||||
|  |  | ||||||
|     @pagy, @users = pagy(manage_users_list) |     @pagy, @users = pagy(manage_users_list) | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -140,6 +142,45 @@ class AdminsController < ApplicationController | |||||||
|  |  | ||||||
|     redirect_to redirect_path, flash: { success: I18n.t("administrator.flash.reset_password") } |     redirect_to redirect_path, flash: { success: I18n.t("administrator.flash.reset_password") } | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   # POST /admins/merge/:user_uid | ||||||
|  |   def merge_user | ||||||
|  |     begin | ||||||
|  |       # Get uid of user that will be merged into the other account | ||||||
|  |       uid_to_merge = params[:merge] | ||||||
|  |       logger.info "#{current_user.uid} is attempting to merge #{uid_to_merge} into #{@user.uid}" | ||||||
|  |  | ||||||
|  |       # Check to make sure the 2 users are unique | ||||||
|  |       raise "Can not merge the user into themself" if uid_to_merge == @user.uid | ||||||
|  |  | ||||||
|  |       # Find user to merge | ||||||
|  |       user_to_merge = User.find_by(uid: uid_to_merge) | ||||||
|  |  | ||||||
|  |       # Move over user's rooms | ||||||
|  |       user_to_merge.rooms.each do |room| | ||||||
|  |         room.owner = @user | ||||||
|  |  | ||||||
|  |         room.name = "(#{I18n.t('merged')}) #{room.name}" | ||||||
|  |  | ||||||
|  |         room.save! | ||||||
|  |       end | ||||||
|  |  | ||||||
|  |       # Reload user to update merge rooms | ||||||
|  |       user_to_merge.reload | ||||||
|  |  | ||||||
|  |       # Delete merged user | ||||||
|  |       user_to_merge.destroy(true) | ||||||
|  |     rescue => e | ||||||
|  |       logger.info "Failed to merge #{uid_to_merge} into #{@user.uid}: #{e}" | ||||||
|  |       flash[:alert] = I18n.t("administrator.flash.merge_fail") | ||||||
|  |     else | ||||||
|  |       logger.info "#{current_user.uid} successfully merged #{uid_to_merge} into #{@user.uid}" | ||||||
|  |       flash[:success] = I18n.t("administrator.flash.merge_success") | ||||||
|  |     end | ||||||
|  |  | ||||||
|  |     redirect_to admins_path | ||||||
|  |   end | ||||||
|  |  | ||||||
|   # SITE SETTINGS |   # SITE SETTINGS | ||||||
|  |  | ||||||
|   # POST /admins/update_settings |   # POST /admins/update_settings | ||||||
|   | |||||||
| @@ -77,7 +77,18 @@ module Populator | |||||||
|       roles_can_appear << role.name if role.get_permission("can_appear_in_share_list") && role.name != "super_admin" |       roles_can_appear << role.name if role.get_permission("can_appear_in_share_list") && role.name != "super_admin" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     initial_list = User.where.not(uid: current_user.uid).with_highest_priority_role(roles_can_appear) |     initial_list = User.where.not(uid: current_user.uid) | ||||||
|  |                        .without_role(:pending) | ||||||
|  |                        .without_role(:denied) | ||||||
|  |                        .with_highest_priority_role(roles_can_appear) | ||||||
|  |  | ||||||
|  |     return initial_list unless Rails.configuration.loadbalanced_configuration | ||||||
|  |     initial_list.where(provider: @user_domain) | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   # Returns a list of users that can merged into another user | ||||||
|  |   def merge_user_list | ||||||
|  |     initial_list = User.where.not(uid: current_user.uid).without_role(:super_admin) | ||||||
|  |  | ||||||
|     return initial_list unless Rails.configuration.loadbalanced_configuration |     return initial_list unless Rails.configuration.loadbalanced_configuration | ||||||
|     initial_list.where(provider: @user_domain) |     initial_list.where(provider: @user_domain) | ||||||
|   | |||||||
| @@ -36,7 +36,7 @@ class Ability | |||||||
|  |  | ||||||
|       if highest_role.get_permission("can_manage_users") |       if highest_role.get_permission("can_manage_users") | ||||||
|         can [:index, :roles, :edit_user, :promote, :demote, :ban_user, :unban_user, |         can [:index, :roles, :edit_user, :promote, :demote, :ban_user, :unban_user, | ||||||
|              :approve, :invite, :reset, :undelete], :admin |              :approve, :invite, :reset, :undelete, :merge_user], :admin | ||||||
|       end |       end | ||||||
|  |  | ||||||
|       can [:index, :server_recordings, :server_rooms], :admin if highest_role.get_permission("can_manage_rooms_recordings") |       can [:index, :server_recordings, :server_rooms], :admin if highest_role.get_permission("can_manage_rooms_recordings") | ||||||
|   | |||||||
| @@ -60,6 +60,11 @@ class Room < ApplicationRecord | |||||||
|     user.rooms.include?(self) |     user.rooms.include?(self) | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   # Determines whether room is a home room | ||||||
|  |   def home_room? | ||||||
|  |     owner.main_room == self | ||||||
|  |   end | ||||||
|  |  | ||||||
|   def shared_users |   def shared_users | ||||||
|     User.where(id: shared_access.pluck(:user_id)) |     User.where(id: shared_access.pluck(:user_id)) | ||||||
|   end |   end | ||||||
|   | |||||||
| @@ -124,6 +124,9 @@ | |||||||
|                               <%= link_to admin_edit_user_path(user_uid: user.uid), class: "dropdown-item" do %> |                               <%= link_to admin_edit_user_path(user_uid: user.uid), class: "dropdown-item" do %> | ||||||
|                                 <i class="dropdown-icon fas fa-user-edit"></i> <%= t("administrator.users.settings.edit") %> |                                 <i class="dropdown-icon fas fa-user-edit"></i> <%= t("administrator.users.settings.edit") %> | ||||||
|                               <% end %> |                               <% end %> | ||||||
|  |                               <button class= "merge-user dropdown-item" data-path="<%= merge_user_path(user_uid: user.uid) %>" data-info="<%= user.slice(:name, :email, :uid).to_json %>" data-toggle="modal" data-target="#mergeUserModal"> | ||||||
|  |                                 <i class="dropdown-icon fas fa-user-friends"></i> <%= t("administrator.users.settings.merge") %> | ||||||
|  |                               </button> | ||||||
|                               <%= button_to admin_ban_path(user_uid: user.uid), class: "dropdown-item", "data-disable": "" do %> |                               <%= button_to admin_ban_path(user_uid: user.uid), class: "dropdown-item", "data-disable": "" do %> | ||||||
|                                 <i class="dropdown-icon fas fa-lock"></i> <%= t("administrator.users.settings.ban") %> |                                 <i class="dropdown-icon fas fa-lock"></i> <%= t("administrator.users.settings.ban") %> | ||||||
|                               <% end %> |                               <% end %> | ||||||
| @@ -157,3 +160,4 @@ | |||||||
|  |  | ||||||
| <%= render "shared/modals/invite_user_modal" %> | <%= render "shared/modals/invite_user_modal" %> | ||||||
| <%= render "shared/modals/delete_account_modal", delete_location: relative_root %> | <%= render "shared/modals/delete_account_modal", delete_location: relative_root %> | ||||||
|  | <%= render "shared/modals/merge_user_modal" %> | ||||||
							
								
								
									
										51
									
								
								app/views/shared/modals/_merge_user_modal.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								app/views/shared/modals/_merge_user_modal.html.erb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | <% | ||||||
|  | # BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. | ||||||
|  | # Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). | ||||||
|  | # This program is free software; you can redistribute it and/or modify it under the | ||||||
|  | # terms of the GNU Lesser General Public License as published by the Free Software | ||||||
|  | # Foundation; either version 3.0 of the License, or (at your option) any later | ||||||
|  | # version. | ||||||
|  | # | ||||||
|  | # BigBlueButton 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 Lesser General Public License for more details. | ||||||
|  | # You should have received a copy of the GNU Lesser General Public License along | ||||||
|  | # with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. | ||||||
|  | %> | ||||||
|  |  | ||||||
|  | <div class="modal fade" id="mergeUserModal" tabindex="-1" role="dialog"> | ||||||
|  |   <div class="modal-dialog modal-dialog-centered" role="document"> | ||||||
|  |     <div class="modal-content text-center"> | ||||||
|  |       <div class="modal-body"> | ||||||
|  |         <div class="card-body p-6"> | ||||||
|  |           <div class="card-title"> | ||||||
|  |             <h3><%= t("modal.merge_user.title") %></h3> | ||||||
|  |           </div> | ||||||
|  |           <select class="selectpicker" title="<%= t("modal.share_access.select") %>" data-live-search="true" data-virtual-scroll="true" > | ||||||
|  |             <% @user_list.each do |user| %> | ||||||
|  |                 <option value="<%= { uid: user.uid, email: user.email, name: user.name }.to_json %>" data-subtext="<%= user.email %>" ><%= user.name %></option> | ||||||
|  |               <% end %> | ||||||
|  |           </select> | ||||||
|  |           <div class="mt-5 text-left row"> | ||||||
|  |             <div class="list-group-item col-6 text-center"> | ||||||
|  |               <label class="form-label text-primary"><%= t("modal.merge_user.from") %></label> | ||||||
|  |                <div id="merge-from"></div> | ||||||
|  |             </div> | ||||||
|  |             <i id="merge-account-arrow" class="fas fa-2x fa-arrow-circle-right text-primary"></i> | ||||||
|  |             <div class="list-group-item col-6 text-center"> | ||||||
|  |               <label class="form-label text-primary"><%= t("modal.merge_user.to") %></label> | ||||||
|  |                <div id="merge-to"></div> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |           <div class="mt-6"> | ||||||
|  |             <button id="merge-save-access" class="btn btn-primary btn-block" onclick="mergeUsers()" ><%= t("modal.merge_user.save") %></button> | ||||||
|  |             <button class="btn btn-secondary text-primary btn-block" onclick="$('#mergeUserModal').modal('hide')"><%= t("modal.merge_user.cancel") %></button> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |         <div class="card-footer"> | ||||||
|  |           <p><%= t("modal.merge_user.footer") %></p> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </div> | ||||||
| @@ -21,7 +21,7 @@ | |||||||
|           <div class="card-title"> |           <div class="card-title"> | ||||||
|             <h3><%= t("modal.share_access.title") %></h3> |             <h3><%= t("modal.share_access.title") %></h3> | ||||||
|           </div> |           </div> | ||||||
|           <select class="selectpicker" title="<%= t("modal.share_access.select") %>..." data-live-search="true" data-virtual-scroll="true" > |           <select class="selectpicker" title="<%= t("modal.share_access.select") %>" data-live-search="true" data-virtual-scroll="true" > | ||||||
|             <% @user_list.each do |user| %> |             <% @user_list.each do |user| %> | ||||||
|                 <option value="<%= user.uid %>" data-subtext="<%= user.uid %>" ><%= user.name %></option> |                 <option value="<%= user.uid %>" data-subtext="<%= user.uid %>" ><%= user.name %></option> | ||||||
|               <% end %> |               <% end %> | ||||||
|   | |||||||
| @@ -84,6 +84,8 @@ en: | |||||||
|       demoted: User has been successfully demoted |       demoted: User has been successfully demoted | ||||||
|       invite: Invite successfully sent to %{email} |       invite: Invite successfully sent to %{email} | ||||||
|       invite_email_verification: Emails must be enabled in order to use this method. Please contact your system administrator. |       invite_email_verification: Emails must be enabled in order to use this method. Please contact your system administrator. | ||||||
|  |       merge_fail: There was an issue merging the user accounts. Please check the users selected and try again  | ||||||
|  |       merge_success: User accounts merged successfully | ||||||
|       perm_deleted: User has been permanently deleted |       perm_deleted: User has been permanently deleted | ||||||
|       promoted: User has been successfully promoted |       promoted: User has been successfully promoted | ||||||
|       registration_method_updated: Registration method successfully updated |       registration_method_updated: Registration method successfully updated | ||||||
| @@ -245,6 +247,8 @@ en: | |||||||
|         body: 'To view the recording, follow the link below:' |         body: 'To view the recording, follow the link below:' | ||||||
|         autogenerated: 'This e-mail is auto-generated by BigBlueButton.' |         autogenerated: 'This e-mail is auto-generated by BigBlueButton.' | ||||||
|         footer: 'BigBlueButton is an open source web conferencing system. For more information on BigBlueButton, see https://bigbluebutton.org/.' |         footer: 'BigBlueButton is an open source web conferencing system. For more information on BigBlueButton, see https://bigbluebutton.org/.' | ||||||
|  |     search: | ||||||
|  |       start: Start searching... | ||||||
|   landing: |   landing: | ||||||
|     about: "%{href} is a simple front-end for your BigBlueButton open-source web conferencing server. You can create your own rooms to host sessions, or join others using a short and convenient link." |     about: "%{href} is a simple front-end for your BigBlueButton open-source web conferencing server. You can create your own rooms to host sessions, or join others using a short and convenient link." | ||||||
|     welcome: Welcome to BigBlueButton. |     welcome: Welcome to BigBlueButton. | ||||||
| @@ -308,6 +312,7 @@ en: | |||||||
|   maintenance: |   maintenance: | ||||||
|     window_alert: Maintenance window scheduled for %{date} |     window_alert: Maintenance window scheduled for %{date} | ||||||
|   max_concurrent: The maximum number of concurrent sessions allowed has been reached! |   max_concurrent: The maximum number of concurrent sessions allowed has been reached! | ||||||
|  |   merged: Merged | ||||||
|   modal: |   modal: | ||||||
|     create_role: |     create_role: | ||||||
|       create: Create a new Role |       create: Create a new Role | ||||||
| @@ -368,6 +373,13 @@ en: | |||||||
|       save: Save Changes |       save: Save Changes | ||||||
|       cancel_changes: Cancel Changes |       cancel_changes: Cancel Changes | ||||||
|       select: Select User |       select: Select User | ||||||
|  |     merge_user: | ||||||
|  |       cancel: Cancel | ||||||
|  |       from: Account to be Merged | ||||||
|  |       title: Merge User Accounts | ||||||
|  |       to: Primary Account | ||||||
|  |       save: Merge | ||||||
|  |       footer: The rooms of the account to be merged will be transfered over to the Primary Account's room list and then the account will be deleted. | ||||||
|   name_update_success: Room name successfully changed! |   name_update_success: Room name successfully changed! | ||||||
|   no_user_email_exists: There is no existing user with the email specified. Please make sure you typed it correctly. |   no_user_email_exists: There is no existing user with the email specified. Please make sure you typed it correctly. | ||||||
|   omniauth_error: An error occured while authenticating with omniauth. Please try again or contact an administrator! |   omniauth_error: An error occured while authenticating with omniauth. Please try again or contact an administrator! | ||||||
|   | |||||||
| @@ -50,6 +50,7 @@ Rails.application.routes.draw do | |||||||
|     post '/approve/:user_uid', to: 'admins#approve', as: :admin_approve |     post '/approve/:user_uid', to: 'admins#approve', as: :admin_approve | ||||||
|     get '/reset', to: 'admins#reset', as: :admin_reset |     get '/reset', to: 'admins#reset', as: :admin_reset | ||||||
|     post '/undelete', to: 'admins#undelete', as: :admin_undelete |     post '/undelete', to: 'admins#undelete', as: :admin_undelete | ||||||
|  |     post '/merge/:user_uid', to: 'admins#merge_user', as: :merge_user | ||||||
|     # Site Settings |     # Site Settings | ||||||
|     post '/update_settings', to: 'admins#update_settings', as: :admin_update_settings |     post '/update_settings', to: 'admins#update_settings', as: :admin_update_settings | ||||||
|     post '/registration_method', to: 'admins#registration_method', as: :admin_change_registration |     post '/registration_method', to: 'admins#registration_method', as: :admin_change_registration | ||||||
|   | |||||||
| @@ -197,6 +197,42 @@ describe AdminsController, type: :controller do | |||||||
|         expect(response).to redirect_to(admins_path) |         expect(response).to redirect_to(admins_path) | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
|  |  | ||||||
|  |     context "POST #merge_user" do | ||||||
|  |       it "merges the users room to the primary account and deletes the old user" do | ||||||
|  |         @request.session[:user_id] = @admin.id | ||||||
|  |  | ||||||
|  |         @user2 = create(:user) | ||||||
|  |         room1 = create(:room, owner: @user2) | ||||||
|  |         room2 = create(:room, owner: @user2) | ||||||
|  |         room3 = @user2.main_room | ||||||
|  |  | ||||||
|  |         post :merge_user, params: { user_uid: @user.uid, merge: @user2.uid } | ||||||
|  |  | ||||||
|  |         room1.reload | ||||||
|  |         room2.reload | ||||||
|  |         room3.reload | ||||||
|  |  | ||||||
|  |         expect(User.exists?(uid: @user2.uid)).to be false | ||||||
|  |         expect(room1.name).to start_with("(Merged)") | ||||||
|  |         expect(room2.name).to start_with("(Merged)") | ||||||
|  |         expect(room3.name).to start_with("(Merged)") | ||||||
|  |         expect(room1.owner).to eq(@user) | ||||||
|  |         expect(room2.owner).to eq(@user) | ||||||
|  |         expect(room3.owner).to eq(@user) | ||||||
|  |         expect(flash[:success]).to be_present | ||||||
|  |         expect(response).to redirect_to(admins_path) | ||||||
|  |       end | ||||||
|  |  | ||||||
|  |       it "does not merge if trying to merge the same user into themself" do | ||||||
|  |         @request.session[:user_id] = @admin.id | ||||||
|  |  | ||||||
|  |         post :merge_user, params: { user_uid: @user.uid, merge: @user.uid } | ||||||
|  |  | ||||||
|  |         expect(flash[:alert]).to be_present | ||||||
|  |         expect(response).to redirect_to(admins_path) | ||||||
|  |       end | ||||||
|  |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   describe "User Design" do |   describe "User Design" do | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user