BigW Consortium Gitlab

project_team_spec.rb 14.8 KB
Newer Older
1 2
require "spec_helper"

3
describe ProjectTeam do
4 5 6 7
  let(:master) { create(:user) }
  let(:reporter) { create(:user) }
  let(:guest) { create(:user) }
  let(:nonmember) { create(:user) }
8

9
  context 'personal project' do
10
    let(:project) { create(:project) }
11

12
    before do
13 14 15
      project.add_master(master)
      project.add_reporter(reporter)
      project.add_guest(guest)
16
    end
17

18
    describe 'members collection' do
19 20 21 22
      it { expect(project.team.masters).to include(master) }
      it { expect(project.team.masters).not_to include(guest) }
      it { expect(project.team.masters).not_to include(reporter) }
      it { expect(project.team.masters).not_to include(nonmember) }
23 24 25
    end

    describe 'access methods' do
26 27 28 29 30 31
      it { expect(project.team.master?(master)).to be_truthy }
      it { expect(project.team.master?(guest)).to be_falsey }
      it { expect(project.team.master?(reporter)).to be_falsey }
      it { expect(project.team.master?(nonmember)).to be_falsey }
      it { expect(project.team.member?(nonmember)).to be_falsey }
      it { expect(project.team.member?(guest)).to be_truthy }
32 33 34
      it { expect(project.team.member?(reporter, Gitlab::Access::REPORTER)).to be_truthy }
      it { expect(project.team.member?(guest, Gitlab::Access::REPORTER)).to be_falsey }
      it { expect(project.team.member?(nonmember, Gitlab::Access::GUEST)).to be_falsey }
35
    end
36 37
  end

38 39
  context 'group project' do
    let(:group) { create(:group) }
40
    let!(:project) { create(:project, group: group) }
41 42

    before do
43 44 45
      group.add_master(master)
      group.add_reporter(reporter)
      group.add_guest(guest)
46 47 48 49

      # If user is a group and a project member - GitLab uses highest permission
      # So we add group guest as master and add group master as guest
      # to this project to test highest access
50 51
      project.add_master(guest)
      project.add_guest(master)
52 53 54
    end

    describe 'members collection' do
55 56 57 58 59
      it { expect(project.team.reporters).to include(reporter) }
      it { expect(project.team.masters).to include(master) }
      it { expect(project.team.masters).to include(guest) }
      it { expect(project.team.masters).not_to include(reporter) }
      it { expect(project.team.masters).not_to include(nonmember) }
60 61 62
    end

    describe 'access methods' do
63 64 65 66 67 68 69
      it { expect(project.team.reporter?(reporter)).to be_truthy }
      it { expect(project.team.master?(master)).to be_truthy }
      it { expect(project.team.master?(guest)).to be_truthy }
      it { expect(project.team.master?(reporter)).to be_falsey }
      it { expect(project.team.master?(nonmember)).to be_falsey }
      it { expect(project.team.member?(nonmember)).to be_falsey }
      it { expect(project.team.member?(guest)).to be_truthy }
70 71 72
      it { expect(project.team.member?(guest, Gitlab::Access::MASTER)).to be_truthy }
      it { expect(project.team.member?(reporter, Gitlab::Access::MASTER)).to be_falsey }
      it { expect(project.team.member?(nonmember, Gitlab::Access::GUEST)).to be_falsey }
73
    end
74
  end
75

76 77
  describe '#fetch_members' do
    context 'personal project' do
78
      let(:project) { create(:project) }
79 80 81

      it 'returns project members' do
        user = create(:user)
82
        project.add_guest(user)
83

84
        expect(project.team.members).to contain_exactly(user, project.owner)
85 86 87 88
      end

      it 'returns project members of a specified level' do
        user = create(:user)
89
        project.add_reporter(user)
90 91 92 93 94 95 96 97 98 99 100 101 102

        expect(project.team.guests).to be_empty
        expect(project.team.reporters).to contain_exactly(user)
      end

      it 'returns invited members of a group' do
        group_member = create(:group_member)

        project.project_group_links.create!(
          group: group_member.group,
          group_access: Gitlab::Access::GUEST
        )

103 104
        expect(project.team.members)
          .to contain_exactly(group_member.user, project.owner)
105 106 107 108 109 110 111 112 113 114
      end

      it 'returns invited members of a group of a specified level' do
        group_member = create(:group_member)

        project.project_group_links.create!(
          group: group_member.group,
          group_access: Gitlab::Access::REPORTER
        )

115
        expect(project.team.guests).to be_empty
116 117 118 119 120 121
        expect(project.team.reporters).to contain_exactly(group_member.user)
      end
    end

    context 'group project' do
      let(:group) { create(:group) }
122
      let!(:project) { create(:project, group: group) }
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138

      it 'returns project members' do
        group_member = create(:group_member, group: group)

        expect(project.team.members).to contain_exactly(group_member.user)
      end

      it 'returns project members of a specified level' do
        group_member = create(:group_member, :reporter, group: group)

        expect(project.team.guests).to be_empty
        expect(project.team.reporters).to contain_exactly(group_member.user)
      end
    end
  end

139 140
  describe '#find_member' do
    context 'personal project' do
141
      let(:project) do
142
        create(:project, :public, :access_requestable)
143 144
      end

145 146 147
      let(:requester) { create(:user) }

      before do
148 149 150
        project.add_master(master)
        project.add_reporter(reporter)
        project.add_guest(guest)
151 152 153 154 155 156 157 158
        project.request_access(requester)
      end

      it { expect(project.team.find_member(master.id)).to be_a(ProjectMember) }
      it { expect(project.team.find_member(reporter.id)).to be_a(ProjectMember) }
      it { expect(project.team.find_member(guest.id)).to be_a(ProjectMember) }
      it { expect(project.team.find_member(nonmember.id)).to be_nil }
      it { expect(project.team.find_member(requester.id)).to be_nil }
159 160
    end

161
    context 'group project' do
162
      let(:group) { create(:group, :access_requestable) }
163
      let(:project) { create(:project, group: group) }
164 165 166 167 168 169 170 171 172 173 174 175 176 177
      let(:requester) { create(:user) }

      before do
        group.add_master(master)
        group.add_reporter(reporter)
        group.add_guest(guest)
        group.request_access(requester)
      end

      it { expect(project.team.find_member(master.id)).to be_a(GroupMember) }
      it { expect(project.team.find_member(reporter.id)).to be_a(GroupMember) }
      it { expect(project.team.find_member(guest.id)).to be_a(GroupMember) }
      it { expect(project.team.find_member(nonmember.id)).to be_nil }
      it { expect(project.team.find_member(requester.id)).to be_nil }
178 179 180
    end
  end

181 182 183 184
  describe "#human_max_access" do
    it 'returns Master role' do
      user = create(:user)
      group = create(:group)
185
      project = create(:project, namespace: group)
186

187
      group.add_master(user)
188 189 190 191 192 193 194

      expect(project.team.human_max_access(user.id)).to eq 'Master'
    end

    it 'returns Owner role' do
      user = create(:user)
      group = create(:group)
195
      project = create(:project, namespace: group)
196

197
      group.add_owner(user)
198 199 200 201 202

      expect(project.team.human_max_access(user.id)).to eq 'Owner'
    end
  end

203 204 205 206
  describe '#max_member_access' do
    let(:requester) { create(:user) }

    context 'personal project' do
207
      let(:project) do
208
        create(:project, :public, :access_requestable)
209
      end
210 211 212

      context 'when project is not shared with group' do
        before do
213 214 215
          project.add_master(master)
          project.add_reporter(reporter)
          project.add_guest(guest)
216 217 218 219 220 221
          project.request_access(requester)
        end

        it { expect(project.team.max_member_access(master.id)).to eq(Gitlab::Access::MASTER) }
        it { expect(project.team.max_member_access(reporter.id)).to eq(Gitlab::Access::REPORTER) }
        it { expect(project.team.max_member_access(guest.id)).to eq(Gitlab::Access::GUEST) }
222 223
        it { expect(project.team.max_member_access(nonmember.id)).to eq(Gitlab::Access::NO_ACCESS) }
        it { expect(project.team.max_member_access(requester.id)).to eq(Gitlab::Access::NO_ACCESS) }
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
      end

      context 'when project is shared with group' do
        before do
          group = create(:group)
          project.project_group_links.create(
            group: group,
            group_access: Gitlab::Access::DEVELOPER)

          group.add_master(master)
          group.add_reporter(reporter)
        end

        it { expect(project.team.max_member_access(master.id)).to eq(Gitlab::Access::DEVELOPER) }
        it { expect(project.team.max_member_access(reporter.id)).to eq(Gitlab::Access::REPORTER) }
239 240
        it { expect(project.team.max_member_access(nonmember.id)).to eq(Gitlab::Access::NO_ACCESS) }
        it { expect(project.team.max_member_access(requester.id)).to eq(Gitlab::Access::NO_ACCESS) }
241 242

        context 'but share_with_group_lock is true' do
243 244 245
          before do
            project.namespace.update(share_with_group_lock: true)
          end
246

247 248
          it { expect(project.team.max_member_access(master.id)).to eq(Gitlab::Access::NO_ACCESS) }
          it { expect(project.team.max_member_access(reporter.id)).to eq(Gitlab::Access::NO_ACCESS) }
249 250
        end
      end
251 252
    end

253
    context 'group project' do
254
      let(:group) { create(:group, :access_requestable) }
255
      let!(:project) do
256
        create(:project, group: group)
257
      end
258 259 260 261 262 263 264 265 266 267 268

      before do
        group.add_master(master)
        group.add_reporter(reporter)
        group.add_guest(guest)
        group.request_access(requester)
      end

      it { expect(project.team.max_member_access(master.id)).to eq(Gitlab::Access::MASTER) }
      it { expect(project.team.max_member_access(reporter.id)).to eq(Gitlab::Access::REPORTER) }
      it { expect(project.team.max_member_access(guest.id)).to eq(Gitlab::Access::GUEST) }
269 270 271 272 273
      it { expect(project.team.max_member_access(nonmember.id)).to eq(Gitlab::Access::NO_ACCESS) }
      it { expect(project.team.max_member_access(requester.id)).to eq(Gitlab::Access::NO_ACCESS) }
    end
  end

274 275 276 277
  describe '#member?' do
    let(:group) { create(:group) }
    let(:developer) { create(:user) }
    let(:master) { create(:user) }
278 279

    let(:personal_project) do
280
      create(:project, namespace: developer.namespace)
281 282 283
    end

    let(:group_project) do
284
      create(:project, namespace: group)
285 286
    end

287 288
    let(:members_project) { create(:project) }
    let(:shared_project) { create(:project) }
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331

    before do
      group.add_master(master)
      group.add_developer(developer)

      members_project.team << [developer, :developer]
      members_project.team << [master, :master]

      create(:project_group_link, project: shared_project, group: group)
    end

    it 'returns false for no user' do
      expect(personal_project.team.member?(nil)).to be(false)
    end

    it 'returns true for personal projects of the user' do
      expect(personal_project.team.member?(developer)).to be(true)
    end

    it 'returns true for projects of groups the user is a member of' do
      expect(group_project.team.member?(developer)).to be(true)
    end

    it 'returns true for projects for which the user is a member of' do
      expect(members_project.team.member?(developer)).to be(true)
    end

    it 'returns true for projects shared on a group the user is a member of' do
      expect(shared_project.team.member?(developer)).to be(true)
    end

    it 'checks for the correct minimum level access' do
      expect(group_project.team.member?(developer, Gitlab::Access::MASTER)).to be(false)
      expect(group_project.team.member?(master, Gitlab::Access::MASTER)).to be(true)
      expect(members_project.team.member?(developer, Gitlab::Access::MASTER)).to be(false)
      expect(members_project.team.member?(master, Gitlab::Access::MASTER)).to be(true)
      expect(shared_project.team.member?(developer, Gitlab::Access::MASTER)).to be(false)
      expect(shared_project.team.member?(master, Gitlab::Access::MASTER)).to be(false)
      expect(shared_project.team.member?(developer, Gitlab::Access::DEVELOPER)).to be(true)
      expect(shared_project.team.member?(master, Gitlab::Access::DEVELOPER)).to be(true)
    end
  end

332
  shared_examples 'max member access for users' do
333
    let(:project) { create(:project) }
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
    let(:group) { create(:group) }
    let(:second_group) { create(:group) }

    let(:master) { create(:user) }
    let(:reporter) { create(:user) }
    let(:guest) { create(:user) }

    let(:promoted_guest) { create(:user) }

    let(:group_developer) { create(:user) }
    let(:second_developer) { create(:user) }

    let(:user_without_access) { create(:user) }
    let(:second_user_without_access) { create(:user) }

    let(:users) do
      [master, reporter, promoted_guest, guest, group_developer, second_developer, user_without_access].map(&:id)
    end

    let(:expected) do
      {
        master.id => Gitlab::Access::MASTER,
        reporter.id => Gitlab::Access::REPORTER,
        promoted_guest.id => Gitlab::Access::DEVELOPER,
        guest.id => Gitlab::Access::GUEST,
        group_developer.id => Gitlab::Access::DEVELOPER,
        second_developer.id => Gitlab::Access::MASTER,
        user_without_access.id => Gitlab::Access::NO_ACCESS
      }
    end

    before do
      project.add_master(master)
      project.add_reporter(reporter)
      project.add_guest(promoted_guest)
      project.add_guest(guest)

      project.project_group_links.create(
        group: group,
        group_access: Gitlab::Access::DEVELOPER
      )

      group.add_master(promoted_guest)
      group.add_developer(group_developer)
      group.add_developer(second_developer)

      project.project_group_links.create(
        group: second_group,
        group_access: Gitlab::Access::MASTER
      )

      second_group.add_master(second_developer)
    end

    it 'returns correct roles for different users' do
      expect(project.team.max_member_access_for_user_ids(users)).to eq(expected)
    end
  end

  describe '#max_member_access_for_user_ids' do
394
    context 'with RequestStore enabled', :request_store do
395
      include_examples 'max member access for users'
396

397 398 399 400 401 402 403 404
      def access_levels(users)
        project.team.max_member_access_for_user_ids(users)
      end

      it 'does not perform extra queries when asked for users who have already been found' do
        access_levels(users)

        expect { access_levels(users) }.not_to exceed_query_limit(0)
405

406
        expect(access_levels(users)).to eq(expected)
407 408
      end

409 410 411 412 413 414 415 416 417
      it 'only requests the extra users when uncached users are passed' do
        new_user = create(:user)
        second_new_user = create(:user)
        all_users = users + [new_user.id, second_new_user.id]

        expected_all = expected.merge(new_user.id => Gitlab::Access::NO_ACCESS,
                                      second_new_user.id => Gitlab::Access::NO_ACCESS)

        access_levels(users)
418

419 420 421 422 423 424 425 426 427 428 429 430 431
        queries = ActiveRecord::QueryRecorder.new { access_levels(all_users) }

        expect(queries.count).to eq(1)
        expect(queries.log_message).to match(/\W#{new_user.id}\W/)
        expect(queries.log_message).to match(/\W#{second_new_user.id}\W/)
        expect(queries.log_message).not_to match(/\W#{promoted_guest.id}\W/)
        expect(access_levels(all_users)).to eq(expected_all)
      end
    end

    context 'with RequestStore disabled' do
      include_examples 'max member access for users'
    end
432
  end
433
end