BigW Consortium Gitlab

user_parser.rb 3.17 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
module Banzai
  module ReferenceParser
    class UserParser < BaseParser
      self.reference_type = :user

      def referenced_by(nodes)
        group_ids = []
        user_ids = []
        project_ids = []

        nodes.each do |node|
          if node.has_attribute?('data-group')
            group_ids << node.attr('data-group').to_i
          elsif node.has_attribute?(self.class.data_attribute)
            user_ids << node.attr(self.class.data_attribute).to_i
          elsif node.has_attribute?('data-project')
            project_ids << node.attr('data-project').to_i
          end
        end

        find_users_for_groups(group_ids) | find_users(user_ids) |
          find_users_for_projects(project_ids)
      end

      def nodes_visible_to_user(user, nodes)
        group_attr = 'data-group'
        groups = lazy { grouped_objects_for_nodes(nodes, Group, group_attr) }
        visible = []
        remaining = []

        nodes.each do |node|
          if node.has_attribute?(group_attr)
33 34 35 36
            next unless can_read_group_reference?(node, user, groups)
            visible << node
          elsif can_read_project_reference?(node)
            visible << node
37 38 39 40 41
          else
            remaining << node
          end
        end

42 43 44 45
        # If project does not belong to a group
        # and does not have the same project id as the current project
        # base class will check if user can read the project that contains
        # the user reference.
46 47 48
        visible + super(current_user, remaining)
      end

49 50 51 52 53 54 55 56 57 58 59 60 61 62
      # Check if project belongs to a group which
      # user can read.
      def can_read_group_reference?(node, user, groups)
        node_group = groups[node.attr('data-group').to_i]

        node_group && can?(user, :read_group, node_group)
      end

      def can_read_project_reference?(node)
        node_id = node.attr('data-project').to_i

        project && project.id == node_id
      end

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
      def nodes_user_can_reference(current_user, nodes)
        project_attr = 'data-project'
        author_attr = 'data-author'

        projects = lazy { projects_for_nodes(nodes) }
        users = lazy { grouped_objects_for_nodes(nodes, User, author_attr) }

        nodes.select do |node|
          project_id = node.attr(project_attr)
          user_id = node.attr(author_attr)

          if project && project_id && project.id == project_id.to_i
            true
          elsif project_id && user_id
            project = projects[project_id.to_i]
            user = users[user_id.to_i]

            project && user ? project.team.member?(user) : false
          else
            true
          end
        end
      end

      def find_users(ids)
        return [] if ids.empty?

90
        collection_objects_for_ids(User, ids)
91 92 93 94 95 96 97 98 99 100 101
      end

      def find_users_for_groups(ids)
        return [] if ids.empty?

        User.joins(:group_members).where(members: { source_id: ids }).to_a
      end

      def find_users_for_projects(ids)
        return [] if ids.empty?

102 103
        collection_objects_for_ids(Project, ids).
          flat_map { |p| p.team.members.to_a }
104
      end
105 106 107 108

      def can_read_reference?(user, ref_project)
        can?(user, :read_project, ref_project)
      end
109 110 111
    end
  end
end