BigW Consortium Gitlab

project_team.rb 5.07 KB
Newer Older
1
class ProjectTeam
2 3 4 5
  attr_accessor :project

  def initialize(project)
    @project = project
6 7 8 9 10 11 12 13
  end

  # Shortcut to add users
  #
  # Use:
  #   @team << [@user, :master]
  #   @team << [@users, :master]
  #
14
  def <<(args)
15
    users, access, current_user = *args
16 17

    if users.respond_to?(:each)
18
      add_users(users, access, current_user)
19
    else
20
      add_user(users, access, current_user)
21
    end
22 23
  end

24
  def find_member(user_id)
25
    member = project.members.find_by(user_id: user_id)
26 27 28

    # If user is not in project members
    # we should check for group membership
29
    if group && !member
30
      member = group.members.find_by(user_id: user_id)
31 32
    end

33
    member
34 35
  end

36
  def add_users(users, access, current_user = nil)
37
    ProjectMember.add_users_into_projects(
38
      [project.id],
39 40 41
      users,
      access,
      current_user
42 43 44
    )
  end

45 46 47 48
  def add_user(user, access, current_user = nil)
    add_users([user], access, current_user)
  end

49 50
  # Remove all users from project team
  def truncate
51
    ProjectMember.truncate_team(project)
52 53 54
  end

  def members
55
    @members ||= fetch_members
56
  end
57
  alias_method :users, :members
58 59

  def guests
60
    @guests ||= fetch_members(:guests)
61 62 63
  end

  def reporters
64
    @reporters ||= fetch_members(:reporters)
65 66 67
  end

  def developers
68
    @developers ||= fetch_members(:developers)
69 70 71
  end

  def masters
72
    @masters ||= fetch_members(:masters)
73
  end
74

75
  def import(source_project, current_user = nil)
76 77
    target_project = project

78
    source_members = source_project.project_members.to_a
79
    target_user_ids = target_project.project_members.pluck(:user_id)
80

81
    source_members.reject! do |member|
82
      # Skip if user already present in team
83
      !member.invite? && target_user_ids.include?(member.user_id)
84 85
    end

86 87 88 89
    source_members.map! do |member|
      new_member = member.dup
      new_member.id = nil
      new_member.source = target_project
90
      new_member.created_by = current_user
91
      new_member
92 93
    end

94
    ProjectMember.transaction do
95 96
      source_members.each do |member|
        member.save
97 98 99 100 101 102 103
      end
    end

    true
  rescue
    false
  end
104

105
  def guest?(user)
106
    max_member_access(user.id) == Gitlab::Access::GUEST
107 108 109
  end

  def reporter?(user)
110
    max_member_access(user.id) == Gitlab::Access::REPORTER
111 112 113
  end

  def developer?(user)
114
    max_member_access(user.id) == Gitlab::Access::DEVELOPER
115 116 117
  end

  def master?(user)
118
    max_member_access(user.id) == Gitlab::Access::MASTER
119 120
  end

121 122 123 124 125 126 127 128
  def member?(user, min_member_access = nil)
    member = !!find_member(user.id)

    if min_member_access
      member && max_member_access(user.id) >= min_member_access
    else
      member
    end
129 130
  end

131 132 133 134
  def human_max_access(user_id)
    Gitlab::Access.options_with_owner.key(max_member_access(user_id))
  end

135 136
  # This method assumes project and group members are eager loaded for optimal
  # performance.
137
  def max_member_access(user_id)
138
    access = []
139

140
    access += project.members.where(user_id: user_id).has_access.pluck(:access_level)
141 142

    if group
143
      access += group.members.where(user_id: user_id).has_access.pluck(:access_level)
144 145
    end

146 147 148 149 150 151 152
    if project.invited_groups.any? && project.allowed_to_share_with_group?
      access << max_invited_level(user_id)
    end

    access.compact.max
  end

153
  private
154 155 156 157 158 159 160 161 162 163 164 165 166 167

  def max_invited_level(user_id)
    project.project_group_links.map do |group_link|
      invited_group = group_link.group
      access = invited_group.group_members.find_by(user_id: user_id).try(:access_field)

      # If group member has higher access level we should restrict it
      # to max allowed access level
      if access && access > group_link.group_access
        access = group_link.group_access
      end

      access
    end.compact.max
168 169
  end

170
  def fetch_members(level = nil)
171 172
    project_members = project.members
    group_members = group ? group.members : []
173 174 175 176 177
    invited_members = []

    if project.invited_groups.any? && project.allowed_to_share_with_group?
      project.project_group_links.each do |group_link|
        invited_group = group_link.group
178
        im = invited_group.members
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201

        if level
          int_level = GroupMember.access_level_roles[level.to_s.singularize.titleize]

          # Skip group members if we ask for masters
          # but max group access is developers
          next if int_level > group_link.group_access

          # If we ask for developers and max
          # group access is developers we need to provide
          # both group master, developers as devs
          if int_level == group_link.group_access
            im.where("access_level >= ?)", group_link.group_access)
          else
            im.send(level)
          end
        end

        invited_members << im
      end

      invited_members = invited_members.flatten.compact
    end
202 203 204

    if level
      project_members = project_members.send(level)
205
      group_members = group_members.send(level) if group
206 207
    end

208
    user_ids = project_members.pluck(:user_id)
209
    user_ids.push(*invited_members.map(&:user_id)) if invited_members.any?
210
    user_ids.push(*group_members.pluck(:user_id)) if group
211 212

    User.where(id: user_ids)
213
  end
214 215 216 217

  def group
    project.group
  end
218
end