Update team users table with new user assignments [SCI-6842]

This commit is contained in:
Oleksii Kriuchykhin 2022-06-01 15:06:19 +02:00
parent 04eaf07c5e
commit c5c3afa906
5 changed files with 113 additions and 131 deletions

View file

@ -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
@ -128,16 +114,16 @@ module Users
Activities::CreateActivityService
.call(activity_type: :remove_user_from_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_removed: @user_t.user.id
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

View file

@ -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)

View file

@ -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

View file

@ -1,10 +1,10 @@
<% if user_team.user == user %>
<% if user_assignment.user == user %>
<div class="btn btn-default btn-xs" type="button" disabled="disabled">
<span class="fas fa-user-cog"></span>
<span class="caret"></span>
</div>
<% else %>
<% id = "user-#{user_team.user.id}-dropdown" %>
<% id = "user-#{user_assignment.user.id}-dropdown" %>
<div class="dropdown dropdown-teams-user">
<div class="btn btn-default btn-xs"
type="button"
@ -19,46 +19,27 @@
<li class="dropdown-header">
<%= t("users.settings.teams.edit.user_dropdown.role_label") %>
</li>
<%= bootstrap_form_for user_team,
<%= bootstrap_form_for user_assignment,
url: update_role_path,
method: :put,
remote: true,
data: { id: 'update-role-form' } do |f| %>
<input type="hidden" name="user_team[role]" data-field="role" value="" %>
<input type="hidden" name="user_assignment[user_role_id]" data-field="role" value="" %>
<% end %>
<li class="user-team-role <%= 'disabled' if user_team.guest? %>">
<% if user_team.guest? %>
<% team_user_roles_collection.each do |user_role| %>
<% same_role = user_assignment.user_role_id == user_role.id %>
<li class="user-team-role <%= 'disabled' if same_role %>">
<% if same_role %>
<span class="fas fa-check"></span>
<%= UserTeam.new(role: 0).role_str %>
<%= user_role.name %>
<% else %>
<a href="#" data-action="submit-role" data-value="guest">
<a href="#" data-action="submit-role" data-value="<%= user_role.id %>">
<span class="fas fa-check"></span>
<%= UserTeam.new(role: 0).role_str %>
<%= user_role.name %>
</a>
<% end %>
</li>
<li class="user-team-role <%= 'disabled' if user_team.normal_user? %>">
<% if user_team.normal_user? %>
<span class="fas fa-check"></span>
<%= UserTeam.new(role: 1).role_str %>
<% else %>
<a href="#" data-action="submit-role" data-value="normal_user">
<span class="fas fa-check"></span>
<%= UserTeam.new(role: 1).role_str %>
</a>
<% end %>
</li>
<li class="user-team-role <%= 'disabled' if user_team.admin? %>">
<% if user_team.admin? %>
<span class="fas fa-check"></span>
<%= UserTeam.new(role: 2).role_str %>
<% else %>
<a href="#" data-action="submit-role" data-value="admin">
<span class="fas fa-check"></span>
<%= UserTeam.new(role: 2).role_str %>
</a>
<% end %>
</li>
<li role="separator" class="divider"></li>
<li>
<%= destroy_uo_link %>

View file

@ -1,12 +1,12 @@
<%= bootstrap_form_for user_team,
url: destroy_user_team_path(user_team, format: :json),
<%= bootstrap_form_for user_assignment,
url: destroy_user_team_path(user_assignment, format: :json),
remote: :true,
method: :delete,
data: { id: 'destroy-user-team-form' } do |f| %>
<p><%= t("users.settings.user_teams.destroy_uo_message",
user: user_team.user.full_name,
team: user_team.team.name) %></p>
<% if user_team.user.confirmed? %>
user: user_assignment.user.full_name,
team: user_assignment.assignable.name) %></p>
<% if user_assignment.user.confirmed? %>
<div class="alert alert-danger" role="alert">
<span class="fas fa-exclamation-triangle"></span>
&nbsp;