Class: ProjectTeam

Inherits:
Object
  • Object
show all
Defined in:
app/models/project_team.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project) ⇒ ProjectTeam

Returns a new instance of ProjectTeam.



6
7
8
# File 'app/models/project_team.rb', line 6

def initialize(project)
  @project = project
end

Instance Attribute Details

#projectObject

Returns the value of attribute project.



4
5
6
# File 'app/models/project_team.rb', line 4

def project
  @project
end

Instance Method Details

#add_developer(user, current_user: nil) ⇒ Object



18
19
20
# File 'app/models/project_team.rb', line 18

def add_developer(user, current_user: nil)
  add_member(user, :developer, current_user: current_user)
end

#add_guest(user, current_user: nil) ⇒ Object



10
11
12
# File 'app/models/project_team.rb', line 10

def add_guest(user, current_user: nil)
  add_member(user, :guest, current_user: current_user)
end

#add_maintainer(user, current_user: nil) ⇒ Object



22
23
24
# File 'app/models/project_team.rb', line 22

def add_maintainer(user, current_user: nil)
  add_member(user, :maintainer, current_user: current_user)
end

#add_member(user, access_level, current_user: nil, expires_at: nil) ⇒ Object



58
59
60
61
62
63
64
65
# File 'app/models/project_team.rb', line 58

def add_member(user, access_level, current_user: nil, expires_at: nil)
  Members::Projects::CreatorService.add_member( # rubocop:disable CodeReuse/ServiceClass
    project,
    user,
    access_level,
    current_user: current_user,
    expires_at: expires_at)
end

#add_members(users, access_level, current_user: nil, expires_at: nil, tasks_to_be_done: [], tasks_project_id: nil) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
# File 'app/models/project_team.rb', line 46

def add_members(users, access_level, current_user: nil, expires_at: nil, tasks_to_be_done: [], tasks_project_id: nil)
  Members::Projects::CreatorService.add_members( # rubocop:disable CodeReuse/ServiceClass
    project,
    users,
    access_level,
    current_user: current_user,
    expires_at: expires_at,
    tasks_to_be_done: tasks_to_be_done,
    tasks_project_id: tasks_project_id
  )
end

#add_owner(user, current_user: nil) ⇒ Object



26
27
28
# File 'app/models/project_team.rb', line 26

def add_owner(user, current_user: nil)
  add_member(user, :owner, current_user: current_user)
end

#add_reporter(user, current_user: nil) ⇒ Object



14
15
16
# File 'app/models/project_team.rb', line 14

def add_reporter(user, current_user: nil)
  add_member(user, :reporter, current_user: current_user)
end

#add_role(user, role, current_user: nil) ⇒ Object



30
31
32
# File 'app/models/project_team.rb', line 30

def add_role(user, role, current_user: nil)
  public_send(:"add_#{role}", user, current_user: current_user) # rubocop:disable GitlabSecurity/PublicSend
end

#contribution_check_for_user_ids(user_ids) ⇒ Object



209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'app/models/project_team.rb', line 209

def contribution_check_for_user_ids(user_ids)
  Gitlab::SafeRequestLoader.execute(
    resource_key: "contribution_check_for_users:#{project.id}",
    resource_ids: user_ids,
    default_value: false
  ) do |user_ids|
    project.merge_requests
           .merged
           .where(author_id: user_ids, target_branch: project.default_branch.to_s)
           .pluck(:author_id)
           .product([true]).to_h
  end
end

#contributor?(user_id) ⇒ Boolean

Returns:

  • (Boolean)


223
224
225
226
227
# File 'app/models/project_team.rb', line 223

def contributor?(user_id)
  return false if max_member_access(user_id) >= Gitlab::Access::GUEST

  contribution_check_for_user_ids([user_id])[user_id]
end

#developer?(user) ⇒ Boolean

Returns:

  • (Boolean)


161
162
163
# File 'app/models/project_team.rb', line 161

def developer?(user)
  max_member_access(user.id) == Gitlab::Access::DEVELOPER
end

#developersObject



98
99
100
# File 'app/models/project_team.rb', line 98

def developers
  @developers ||= fetch_members(Gitlab::Access::DEVELOPER)
end

#find_member(user_id) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
# File 'app/models/project_team.rb', line 34

def find_member(user_id)
  member = project.members.find_by(user_id: user_id)

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

  member
end

#guest?(user) ⇒ Boolean

Returns:

  • (Boolean)


153
154
155
# File 'app/models/project_team.rb', line 153

def guest?(user)
  max_member_access(user.id) == Gitlab::Access::GUEST
end

#guestsObject



90
91
92
# File 'app/models/project_team.rb', line 90

def guests
  @guests ||= fetch_members(Gitlab::Access::GUEST)
end

#human_max_access(user_id) ⇒ Object



177
178
179
# File 'app/models/project_team.rb', line 177

def human_max_access(user_id)
  Gitlab::Access.human_access(max_member_access(user_id))
end

#import(source_project, current_user) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'app/models/project_team.rb', line 121

def import(source_project, current_user)
  target_project = project

  source_members = source_project.project_members.to_a
  target_user_ids = target_project.project_members.pluck_user_ids

  importer_access_level = max_member_access(current_user.id)

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

  source_members.map! do |member|
    new_member = member.dup
    new_member.id = nil
    new_member.source = target_project
    # So that a maintainer cannot import a member with owner access
    new_member.access_level = [new_member.access_level, importer_access_level].min
    new_member.created_by = current_user
    new_member
  end

  ProjectMember.transaction do
    source_members.each(&:save)
  end

  source_members
rescue StandardError
  false
end

#maintainer?(user) ⇒ Boolean

Returns:

  • (Boolean)


165
166
167
# File 'app/models/project_team.rb', line 165

def maintainer?(user)
  max_member_access(user.id) == Gitlab::Access::MAINTAINER
end

#maintainersObject



102
103
104
# File 'app/models/project_team.rb', line 102

def maintainers
  @maintainers ||= fetch_members(Gitlab::Access::MAINTAINER)
end

#max_member_access(user_id) ⇒ Object



205
206
207
# File 'app/models/project_team.rb', line 205

def max_member_access(user_id)
  max_member_access_for_user_ids([user_id])[user_id]
end

#max_member_access_for_user_ids(user_ids) ⇒ Object

Determine the maximum access level for a group of users in bulk.

Returns a Hash mapping user ID -> maximum access level.



184
185
186
187
188
189
190
191
192
193
194
195
# File 'app/models/project_team.rb', line 184

def max_member_access_for_user_ids(user_ids)
  Gitlab::SafeRequestLoader.execute(
    resource_key: project.max_member_access_for_resource_key(User),
    resource_ids: user_ids,
    default_value: Gitlab::Access::NO_ACCESS
  ) do |user_ids|
    project.project_authorizations
           .where(user: user_ids)
           .group(:user_id)
           .maximum(:access_level)
  end
end

#member?(user, min_access_level = Gitlab::Access::GUEST) ⇒ Boolean

Checks if ‘user` is authorized for this project, with at least the `min_access_level` (if given).

Returns:

  • (Boolean)


171
172
173
174
175
# File 'app/models/project_team.rb', line 171

def member?(user, min_access_level = Gitlab::Access::GUEST)
  return false unless user

  max_member_access(user.id) >= min_access_level
end

#membersObject Also known as: users



72
73
74
# File 'app/models/project_team.rb', line 72

def members
  @members ||= fetch_members
end

#members_in_project_and_ancestorsObject

‘members` method uses project_authorizations table which is updated asynchronously, on project move it still contains old members who may not have access to the new location, so we filter out only members of project or project’s group



81
82
83
84
# File 'app/models/project_team.rb', line 81

def members_in_project_and_ancestors
  members.where(id: member_user_ids)
    .allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/422405')
end

#members_with_access_levels(access_levels = []) ⇒ Object



86
87
88
# File 'app/models/project_team.rb', line 86

def members_with_access_levels(access_levels = [])
  fetch_members(access_levels)
end

#owner?(user) ⇒ Boolean

Returns:

  • (Boolean)


117
118
119
# File 'app/models/project_team.rb', line 117

def owner?(user)
  owners.include?(user)
end

#ownersObject



106
107
108
109
110
111
112
113
114
115
# File 'app/models/project_team.rb', line 106

def owners
  @owners ||=
    if group
      group.owners
    else
      # workaround until we migrate Project#owners to have membership with
      # OWNER access level
      Array.wrap(fetch_members(Gitlab::Access::OWNER)) | Array.wrap(project.owner)
    end
end

#purge_member_access_cache_for_user_id(user_id) ⇒ Object



201
202
203
# File 'app/models/project_team.rb', line 201

def purge_member_access_cache_for_user_id(user_id)
  project.purge_resource_id_from_request_store(User, user_id)
end

#reporter?(user) ⇒ Boolean

Returns:

  • (Boolean)


157
158
159
# File 'app/models/project_team.rb', line 157

def reporter?(user)
  max_member_access(user.id) == Gitlab::Access::REPORTER
end

#reportersObject



94
95
96
# File 'app/models/project_team.rb', line 94

def reporters
  @reporters ||= fetch_members(Gitlab::Access::REPORTER)
end

#truncateObject

Remove all users from project team



68
69
70
# File 'app/models/project_team.rb', line 68

def truncate
  ProjectMember.truncate_team(project)
end

#write_member_access_for_user_id(user_id, project_access_level) ⇒ Object



197
198
199
# File 'app/models/project_team.rb', line 197

def write_member_access_for_user_id(user_id, project_access_level)
  project.merge_value_to_request_store(User, user_id, project_access_level)
end