project_team.rb 4.12 KB
Newer Older
1
class ProjectTeam
2 3
  include BulkMemberAccessLoad

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
4 5 6 7
  attr_accessor :project

  def initialize(project)
    @project = project
8 9 10 11 12 13 14 15
  end

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

    if users.respond_to?(:each)
20
      add_users(users, access, current_user: current_user)
21
    else
22
      add_user(users, access, current_user: current_user)
23
    end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
24 25
  end

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
  def add_guest(user, current_user: nil)
    self << [user, :guest, current_user]
  end

  def add_reporter(user, current_user: nil)
    self << [user, :reporter, current_user]
  end

  def add_developer(user, current_user: nil)
    self << [user, :developer, current_user]
  end

  def add_master(user, current_user: nil)
    self << [user, :master, current_user]
  end

Douwe Maan's avatar
Douwe Maan committed
42
  def find_member(user_id)
43
    member = project.members.find_by(user_id: user_id)
44 45 46

    # If user is not in project members
    # we should check for group membership
Douwe Maan's avatar
Douwe Maan committed
47
    if group && !member
48
      member = group.members.find_by(user_id: user_id)
49 50
    end

Douwe Maan's avatar
Douwe Maan committed
51
    member
52 53
  end

54
  def add_users(users, access_level, current_user: nil, expires_at: nil)
55 56
    ProjectMember.add_users(
      project,
57
      users,
58
      access_level,
59 60
      current_user: current_user,
      expires_at: expires_at
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
61 62 63
    )
  end

64 65 66 67 68 69 70 71
  def add_user(user, access_level, current_user: nil, expires_at: nil)
    ProjectMember.add_user(
      project,
      user,
      access_level,
      current_user: current_user,
      expires_at: expires_at
    )
72 73
  end

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
74 75
  # Remove all users from project team
  def truncate
76
    ProjectMember.truncate_team(project)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
77 78 79
  end

  def members
80
    @members ||= fetch_members
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
81
  end
82
  alias_method :users, :members
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
83 84

  def guests
85
    @guests ||= fetch_members(Gitlab::Access::GUEST)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
86 87 88
  end

  def reporters
89
    @reporters ||= fetch_members(Gitlab::Access::REPORTER)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
90 91 92
  end

  def developers
93
    @developers ||= fetch_members(Gitlab::Access::DEVELOPER)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
94 95 96
  end

  def masters
97
    @masters ||= fetch_members(Gitlab::Access::MASTER)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
98
  end
99

100
  def import(source_project, current_user = nil)
101 102
    target_project = project

Douwe Maan's avatar
Douwe Maan committed
103
    source_members = source_project.project_members.to_a
104
    target_user_ids = target_project.project_members.pluck(:user_id)
105

Douwe Maan's avatar
Douwe Maan committed
106
    source_members.reject! do |member|
107
      # Skip if user already present in team
108
      !member.invite? && target_user_ids.include?(member.user_id)
109 110
    end

Douwe Maan's avatar
Douwe Maan committed
111 112 113 114
    source_members.map! do |member|
      new_member = member.dup
      new_member.id = nil
      new_member.source = target_project
115
      new_member.created_by = current_user
Douwe Maan's avatar
Douwe Maan committed
116
      new_member
117 118
    end

119
    ProjectMember.transaction do
Douwe Maan's avatar
Douwe Maan committed
120 121
      source_members.each do |member|
        member.save
122 123 124 125 126 127 128
      end
    end

    true
  rescue
    false
  end
129

130
  def guest?(user)
Douwe Maan's avatar
Douwe Maan committed
131
    max_member_access(user.id) == Gitlab::Access::GUEST
132 133 134
  end

  def reporter?(user)
Douwe Maan's avatar
Douwe Maan committed
135
    max_member_access(user.id) == Gitlab::Access::REPORTER
136 137 138
  end

  def developer?(user)
Douwe Maan's avatar
Douwe Maan committed
139
    max_member_access(user.id) == Gitlab::Access::DEVELOPER
140 141 142
  end

  def master?(user)
Douwe Maan's avatar
Douwe Maan committed
143
    max_member_access(user.id) == Gitlab::Access::MASTER
144 145
  end

146 147 148 149 150
  # Checks if `user` is authorized for this project, with at least the
  # `min_access_level` (if given).
  def member?(user, min_access_level = Gitlab::Access::GUEST)
    return false unless user

151
    max_member_access(user.id) >= min_access_level
152 153
  end

154
  def human_max_access(user_id)
155
    Gitlab::Access.human_access(max_member_access(user_id))
156 157
  end

158 159
  # Determine the maximum access level for a group of users in bulk.
  #
Stan Hu's avatar
Stan Hu committed
160
  # Returns a Hash mapping user ID -> maximum access level.
161
  def max_member_access_for_user_ids(user_ids)
162 163 164 165 166
    max_member_access_for_resource_ids(User, user_ids, project.id) do |user_ids|
      project.project_authorizations
             .where(user: user_ids)
             .group(:user_id)
             .maximum(:access_level)
167
    end
168 169 170
  end

  def max_member_access(user_id)
171
    max_member_access_for_user_ids([user_id])[user_id]
172 173
  end

174
  private
175

176
  def fetch_members(level = nil)
177 178
    members = project.authorized_users
    members = members.where(project_authorizations: { access_level: level }) if level
179

180
    members
181
  end
182 183 184 185

  def group
    project.group
  end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
186
end