diff --git a/app/controllers/users/settings/user_teams_controller.rb b/app/controllers/users/settings/user_teams_controller.rb index dd9b468be..7c97fd473 100644 --- a/app/controllers/users/settings/user_teams_controller.rb +++ b/app/controllers/users/settings/user_teams_controller.rb @@ -3,45 +3,33 @@ module Users class UserTeamsController < ApplicationController include NotificationsHelper include InputSanitizeHelper + include UserRolesHelper - before_action :load_user, only: :destroy - - before_action :load_user_team, only: [ - :update, - :leave_html, - :destroy_html, - :destroy - ] + before_action :load_user_assignment, only: %i(update leave_html destroy_html destroy) + before_action :check_manage_permissions def update respond_to do |format| - if @user_t.update(update_params) - # If user is administrator of team, - # and he/she changes his/her role - # he/she should be redirected to teams page - new_path = teams_path if @user_t.user == @current_user && - @user_t.role != 'admin' - + if @user_assignment.update(update_params) Activities::CreateActivityService .call(activity_type: :change_users_role_on_team, owner: current_user, - subject: @user_t.team, - team: @user_t.team, + subject: @user_assignment.assignable, + team: @user_assignment.assignable, message_items: { - team: @user_t.team.id, - user_changed: @user_t.user.id, - role: @user_t.role_str + team: @user_assignment.assignable.id, + user_changed: @user_assignment.user.id, + role: @user_assignment.user_role.name }) format.json do render json: { - status: :ok, - new_path: new_path + status: :ok } end else format.json do - render json: @user_t.errors, + render json: @user_assignment.errors, status: :unprocessable_entity end end @@ -53,14 +41,12 @@ module Users format.json do render json: { html: render_to_string( - partial: - 'users/settings/user_teams/' \ - 'leave_user_team_modal_body.html.erb', - locals: { user_team: @user_t } + partial: 'users/settings/user_teams/leave_user_team_modal_body.html.erb', + locals: { user_assignment: @user_assignment } ), heading: I18n.t( 'users.settings.user_teams.leave_uo_heading', - team: escape_input(@user_t.team.name) + team: escape_input(@user_assignment.assignable.name) ) } end @@ -74,12 +60,12 @@ module Users html: render_to_string( partial: 'users/settings/user_teams/' \ 'destroy_user_team_modal_body.html.erb', - locals: { user_team: @user_t } + locals: { user_assignment: @user_assignment } ), heading: I18n.t( 'users.settings.user_teams.destroy_uo_heading', - user: escape_input(@user_t.user.full_name), - team: escape_input(@user_t.team.name) + user: escape_input(@user_assignment.user.full_name), + team: escape_input(@user_assignment.assignable.name) ) } end @@ -90,11 +76,11 @@ module Users # If user is last administrator of team, # he/she cannot be deleted from it. invalid = - @user_t.admin? && - @user_t - .team - .user_teams - .where(role: 2) + managing_team_user_roles_collection.include?(@user_assignment.user_role) && + @user_assignment + .assignable + .user_assignments + .where(user_role: managing_team_user_roles_collection) .count <= 1 unless invalid @@ -105,20 +91,20 @@ module Users # administrator of team if params[:leave] new_owner = - @user_t - .team - .user_teams - .where(role: 2) - .where.not(id: @user_t.id) + @user_assignment + .assignable + .user_assignments + .where(user_role: managing_team_user_roles_collection) + .where.not(id: @user_assignment.id) .first .user Activities::CreateActivityService .call(activity_type: :user_leave_team, owner: current_user, - subject: @user_t.team, - team: @user_t.team, + subject: @user_assignment.assignable, + team: @user_assignment.assignable, message_items: { - team: @user_t.team.id + team: @user_assignment.assignable.id }) else # Otherwise, the new owner for projects is @@ -126,18 +112,18 @@ module Users # the user from the team) new_owner = current_user Activities::CreateActivityService - .call(activity_type: :remove_user_from_team, - owner: current_user, - subject: @user_t.team, - team: @user_t.team, - message_items: { - team: @user_t.team.id, - user_removed: @user_t.user.id - }) + .call(activity_type: :remove_user_from_team, + owner: current_user, + subject: @user_assignment.assignable, + team: @user_assignment.assignable, + message_items: { + team: @user_assignment.assignable.id, + user_removed: @user_assignment.user.id + }) end - reset_user_current_team(@user_t) + reset_user_current_team(@user_assignment) - @user_t.destroy(new_owner) + remove_user_from_team!(@user_assignment, new_owner) end rescue StandardError => e Rails.logger.error e.message @@ -150,18 +136,18 @@ module Users if params[:leave] flash[:notice] = I18n.t( 'users.settings.user_teams.leave_flash', - team: @user_t.team.name + team: @user_assignment.assignable.name ) flash.keep(:notice) end generate_notification(current_user, - @user_t.user, - @user_t.team, + @user_assignment.user, + @user_assignment.assignable, false) format.json { render json: { status: :ok } } else format.json do - render json: @user_t.errors, + render json: @user_assignment.errors, status: :unprocessable_entity end end @@ -170,32 +156,44 @@ module Users private - def load_user - @user = current_user + def load_user_assignment + @user_assignment = UserAssignment.find_by(id: params[:id]) end - def load_user_team - @user_t = UserTeam.find_by_id(params[:id]) - @team = @user_t.team - # Don't allow the user to modify UserTeam-s if he's not admin, - # unless he/she is modifying his/her UserTeam - if current_user != @user_t.user && - !can_manage_team_users?(@user_t.team) - render_403 - end + def check_manage_permissions + render_403 unless can_manage_team_users?(@user_assignment.assignable) end def update_params - params.require(:user_team).permit( - :role - ) + params.require(:user_assignment).permit(:user_role_id) end - def reset_user_current_team(user_team) - ids = user_team.user.teams_ids - ids -= [user_team.team.id] - user_team.user.current_team_id = ids.first - user_team.user.save + def reset_user_current_team(user_assignment) + ids = user_assignment.user.teams_ids + ids -= [user_assignment.assignable.id] + user_assignment.user.current_team_id = ids.first + user_assignment.user.save + end + + def remove_user_from_team!(user_assignment, new_owner) + return user_assignment.destroy! unless new_owner + + # Also, make new owner author of all protocols that belong + # to the departing user and belong to this team. + p_ids = user_assignment.user.added_protocols.where(team: user_assignment.assignable).pluck(:id) + Protocol.where(id: p_ids).find_each do |protocol| + protocol.record_timestamps = false + protocol.added_by = new_owner + protocol.archived_by = new_owner unless protocol.archived_by.nil? + protocol.restored_by = new_owner unless protocol.restored_by.nil? + protocol.save! + end + + # Make new owner author of all inventory items that were added + # by departing user and belong to this team. + RepositoryRow.change_owner(user_assignment.assignable, user_assignment.user, new_owner) + + user_assignment.destroy! end end end diff --git a/app/datatables/team_users_datatable.rb b/app/datatables/team_users_datatable.rb index 56250789b..d4362a46d 100644 --- a/app/datatables/team_users_datatable.rb +++ b/app/datatables/team_users_datatable.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class TeamUsersDatatable < CustomDatatable include InputSanitizeHelper include ActiveRecord::Sanitization::ClassMethods @@ -16,8 +18,8 @@ class TeamUsersDatatable < CustomDatatable @sortable_columns ||= [ 'User.full_name', 'User.email', - 'UserTeam.role', - 'UserTeam.created_at', + 'UserRole.name', + 'UserAssignment.created_at', 'User.status' ] end @@ -26,7 +28,7 @@ class TeamUsersDatatable < CustomDatatable @searchable_columns ||= [ 'User.full_name', 'User.email', - 'UserTeam.created_at' + 'UserAssignment.created_at' ] end @@ -61,13 +63,13 @@ class TeamUsersDatatable < CustomDatatable 'DT_RowId': record.id, '0': escape_input(record.user.full_name), '1': escape_input(record.user.email), - '2': record.role_str, + '2': record.user_role.name, '3': I18n.l(record.created_at, format: :full_date), '4': record.user.active_status_str, '5': ApplicationController.new.render_to_string( partial: 'users/settings/teams/user_dropdown.html.erb', locals: { - user_team: record, + user_assignment: record, update_role_path: update_user_team_path(record, format: :json), destroy_uo_link: link_to( I18n.t('users.settings.teams.edit.user_dropdown.remove_label'), @@ -95,19 +97,16 @@ class TeamUsersDatatable < CustomDatatable # Query database for records (this will be later paginated and filtered) # after that "data" function will return json def get_raw_records - UserTeam - .includes(:user) - .references(:user) - .where(team: @team) - .distinct + @team.user_assignments.includes(:user) end def sort_records(records) - if sort_column(order_params) == 'users.status' + case sort_column(order_params) + when 'users.status' records = records.sort_by { |record| record.user.active_status_str } order_params['dir'] == 'asc' ? records : records.reverse - elsif sort_column(order_params) == 'user_teams.role' - records = records.sort_by(&:role_str) + when 'user_roles.name' + records = records.sort_by { |record| record.user_role.name } order_params['dir'] == 'asc' ? records : records.reverse else super(records) diff --git a/app/helpers/user_roles_helper.rb b/app/helpers/user_roles_helper.rb index 4d0508e11..9ebc9b252 100644 --- a/app/helpers/user_roles_helper.rb +++ b/app/helpers/user_roles_helper.rb @@ -16,4 +16,8 @@ module UserRolesHelper .sort_by { |user_role| (user_role.permissions & team_permissions).length } .reverse! end + + def managing_team_user_roles_collection + UserRole.where('permissions && ARRAY[?]::varchar[]', [TeamPermissions::USERS_MANAGE]) + end end diff --git a/app/views/users/settings/teams/_user_dropdown.html.erb b/app/views/users/settings/teams/_user_dropdown.html.erb index 7b0634dad..ac27f9016 100644 --- a/app/views/users/settings/teams/_user_dropdown.html.erb +++ b/app/views/users/settings/teams/_user_dropdown.html.erb @@ -1,10 +1,10 @@ -<% if user_team.user == user %> +<% if user_assignment.user == user %>
<%= t("users.settings.user_teams.destroy_uo_message", - user: user_team.user.full_name, - team: user_team.team.name) %>
- <% if user_team.user.confirmed? %> + user: user_assignment.user.full_name, + team: user_assignment.assignable.name) %> + <% if user_assignment.user.confirmed? %>