# 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