# frozen_string_literal: true module Shareable extend ActiveSupport::Concern included do has_many :team_shared_objects, as: :shared_object, dependent: :destroy has_many :teams_shared_with, through: :team_shared_objects, source: :team, dependent: :destroy if column_names.include? 'permission_level' enum permission_level: Extends::SHARED_OBJECTS_PERMISSION_LEVELS define_method :globally_shareable? do true end else # If model does not include the permission_level column for global sharing, # all related methods should just return false Extends::SHARED_OBJECTS_PERMISSION_LEVELS.each do |level| define_method "#{level[0]}?" do level[0] == :not_shared end define_method :globally_shareable? do false end end end scope :shared_with_team, lambda { |team| directly_shared = joins(:team_shared_objects, :team).where(team_shared_objects: { team: team }) globally_shared = if column_names.include?('permission_level') where( permission_level: [ Extends::SHARED_OBJECTS_PERMISSION_LEVELS[:shared_read], Extends::SHARED_OBJECTS_PERMISSION_LEVELS[:shared_write] ] ) else none end where(id: directly_shared.select(:id)).or(where(id: globally_shared.select(:id))) } rescue ActiveRecord::NoDatabaseError, ActiveRecord::ConnectionNotEstablished, ActiveRecord::StatementInvalid, PG::ConnectionBad Rails.logger.info('Not connected to database, skipping sharable model initialization.') end def can_manage_shared?(user) globally_shared? || (shared_with?(user.current_team) && user.current_team.permission_granted?(user, TeamPermissions::MANAGE)) end def shareable_write? true end def private_shared_with?(team) team_shared_objects.exists?(team: team) end def private_shared_with_read?(team) team_shared_objects.exists?(team: team, permission_level: :shared_read) end def private_shared_with_write?(team) team_shared_objects.exists?(team: team, permission_level: :shared_write) end def i_shared?(team) shared_with_anybody? && self.team == team end def globally_shared? shared_read? || shared_write? end def shared_with_anybody? (!not_shared? || team_shared_objects.any?) end def shared_with?(team) return false if self.team == team !not_shared? || private_shared_with?(team) end def shared_with_write?(team) return false if self.team == team shared_write? || private_shared_with_write?(team) end def shared_with_read?(team) return false if self.team == team shared_read? || team_shared_objects.exists?(team: team, permission_level: :shared_read) end def demote_all_sharing_assignments_to_viewer!(for_team: nil) # take into account special roles with no read permission, and do not upgrade them to viewer read_permission = "#{self.class.permission_class}Permissions".constantize::READ teams = for_team ? Team.where(id: for_team.id).where.not(id: team.id) : Team.where.not(id: team.id) [user_assignments, user_group_assignments, team_assignments].each do |assignments| assignments.joins(:user_role) .where(team_id: teams.select(:id)) .where(['user_roles.permissions @> ARRAY[?]::varchar[]', [read_permission]]) .update!(user_role: UserRole.find_predefined_viewer_role) end end def destroy_all_sharing_assignments!(for_team: nil) teams = for_team ? Team.where(id: for_team.id).where.not(id: team.id) : Team.where.not(id: team.id) user_assignments.where(team_id: teams.select(:id)).destroy_all user_group_assignments.where.not(team_id: teams.select(:id)).destroy_all team_assignments.where.not(team_id: teams.select(:id)).destroy_all end end