scinote-web/app/controllers/access_permissions/base_controller.rb
2025-08-14 14:53:04 +02:00

200 lines
7.6 KiB
Ruby

# frozen_string_literal: true
module AccessPermissions
class BaseController < ApplicationController
include InputSanitizeHelper
include UserRolesHelper
before_action :set_model
before_action :set_assignment, only: %i(create update destroy)
before_action :check_read_permissions, only: %i(show show_user_group_assignments user_roles)
before_action :check_manage_permissions, except: %i(show show_user_group_assignments user_roles)
before_action :load_available_users, only: %i(new create)
def show
render json: @model.user_assignments.where(team: current_team).includes(:user_role, :user).order('users.full_name ASC'),
each_serializer: UserAssignmentSerializer, user: current_user
end
def new
render json: @available_users, each_serializer: UserSerializer, user: current_user
end
def edit; end
def create
ActiveRecord::Base.transaction do
@assignment.update!(
user_role_id: permitted_params[:user_role_id],
assigned_by: current_user,
assigned: :manually
)
case assignment_type
when :team
log_activity(:"#{model_parameter}_access_granted_all_team_members", team: @assignment.team.id, role: @assignment.user_role.name)
when :user
log_activity(:"#{model_parameter}_access_granted", user_target: @assignment.user.id, role: @assignment.user_role.name)
when :user_group
log_activity(:"#{model_parameter}_access_granted_user_group", user_group: @assignment.user_group.id, role: @assignment.user_role.name)
end
propagate_job
@message = if assignment_type == :team
t('access_permissions.create.success', member_name: t('access_permissions.all_team'))
else
t('access_permissions.create.success', member_name: escape_input(assignment_type == :user_group ? @assignment.user_group.name : @assignment.user.name))
end
render json: { message: @message }
rescue ActiveRecord::RecordInvalid => e
Rails.logger.error e.message
errors = @model.errors.present? ? @model.errors&.map(&:message)&.join(',') : e.message
render json: { flash: errors }, status: :unprocessable_entity
raise ActiveRecord::Rollback
end
end
def update
# prevent role change if it would result in no manually assigned users having the user management permission
new_user_role = UserRole.find(permitted_params[:user_role_id])
if permitted_params[:user_id].present? && permitted_params[:user_id] != 'all' && !new_user_role.has_permission?(manage_permission_constant) &&
@assignment.last_with_permission?(manage_permission_constant, assigned: :manually)
raise ActiveRecord::RecordInvalid
end
@assignment.update!(user_role_id: permitted_params[:user_role_id], assigned_by: current_user)
case assignment_type
when :team
log_activity(:"#{model_parameter}_access_changed_all_team_members", team: @assignment.team.id, role: @assignment.user_role.name)
when :user
log_activity(:"#{model_parameter}_access_changed", user_target: @assignment.user.id, role: @assignment.user_role.name)
when :user_group
log_activity(:"#{model_parameter}_access_changed_user_group", user_group: @assignment.user_group.id, role: @assignment.user_role.name)
end
propagate_job
render json: { user_role_id: @assignment.user_role_id }, status: :ok
rescue ActiveRecord::RecordInvalid
render json: { flash: t('access_permissions.update.failure') }, status: :unprocessable_entity
end
def destroy
# prevent deletion of last manually assigned user that can manage users
if params[:user_id].present? && params[:user_id] != 'all' && @assignment.last_with_permission?(manage_permission_constant, assigned: :manually)
raise ActiveRecord::RecordInvalid
end
UserAssignments::PropagateAssignmentJob.perform_now(@assignment, destroy: true)
case assignment_type
when :team
@assigned_name = @assignment.team.name
log_activity(:"#{model_parameter}_access_revoked_all_team_members", team: @assignment.team.id, role: @assignment.user_role.name)
when :user_group
@assigned_name = @assignment.user_group.name
log_activity(:"#{model_parameter}_access_revoked_user_group", user_group: @assignment.user_group.id, role: @assignment.user_role.name)
when :user
@assigned_name = @assignment.user.full_name
log_activity(:"#{model_parameter}_access_revoked", user_target: @assignment.user.id, role: @assignment.user_role.name)
end
render json: { message: t('access_permissions.destroy.success', member_name: escape_input(@assigned_name)) }
rescue ActiveRecord::RecordInvalid
render json: { message: t('access_permissions.destroy.failure') },
status: :unprocessable_entity
end
def show_user_group_assignments
render json: @model.user_group_assignments.where(team: current_team).includes(:user_role, :user_group).order('user_groups.name ASC'),
each_serializer: UserGroupAssignmentSerializer, user: current_user
end
def unassigned_user_groups
render json: current_team.user_groups.where.not(id: @model.user_group_assignments.select(:user_group_id)),
each_serializer: UserGroupSerializer, user: current_user
end
def user_roles
render json: { data: user_roles_collection(@model).map(&:reverse) }
end
private
def model_parameter
@model.class.permission_class.model_name.param_key
end
def manage_permission_constant
"#{@model.class.permission_class.name}Permissions::USERS_MANAGE".constantize
end
def permitted_default_public_user_role_params
params.require(:object).permit(:default_public_user_role_id)
end
def permitted_params
params.require(:user_assignment)
.permit(%i(user_role_id user_id user_group_id team_id))
end
def load_available_users
@available_users = current_team.users.where.not(id: @model.user_assignments.where(team: current_team).select(:user_id)).order(users: { full_name: :asc })
end
def propagate_job(destroy: false)
return unless @model.has_permission_children?
UserAssignments::PropagateAssignmentJob.perform_later(
@assignment,
destroy: destroy
)
end
def check_manage_permissions
raise NotImplementedError
end
def check_read_permissions
raise NotImplementedError
end
def log_activity(type_of, message_items = {})
message_items = { model_parameter => @model.id }.merge(message_items)
Activities::CreateActivityService
.call(activity_type: type_of,
owner: current_user,
subject: @model,
team: @model.team,
project: @project,
message_items: message_items)
end
def set_assignment
case assignment_type
when :user, :user_group
@assignment = @model.public_send(:"#{assignment_type}_assignments").find_or_initialize_by(
"#{assignment_type}_id": permitted_params[:"#{assignment_type}_id"],
team: current_team
)
when :team
@assignment =
@model.team_assignments
.find_or_initialize_by(team: current_team, assignable: @model)
end
end
def assignment_type
if permitted_params[:team_id].present? || permitted_params[:user_id] == 'all'
:team
elsif permitted_params[:user_group_id].present?
:user_group
elsif permitted_params[:user_id].present?
:user
end
end
end
end