Commit b695ed10 authored by Jason Goodman's avatar Jason Goodman Committed by Imre Farkas

Handle pending project memberships

Restrict authorizable scope to only active memberships
parent 0f7bf7f0
...@@ -117,6 +117,7 @@ class Member < ApplicationRecord ...@@ -117,6 +117,7 @@ class Member < ApplicationRecord
# to projects/groups. # to projects/groups.
scope :authorizable, -> do scope :authorizable, -> do
connected_to_user connected_to_user
.active_state
.non_request .non_request
.non_minimal_access .non_minimal_access
end end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Pending project memberships', :js do
let_it_be(:developer) { create(:user) }
before do
sign_in(developer)
end
context 'with a private project in a private group' do
let_it_be(:group) { create(:group, :private) }
let_it_be(:project) { create(:project, :private, namespace: group) }
let_it_be(:membership) { create(:project_member, :awaiting, :developer, source: project, user: developer) }
it 'a pending project member gets a 404 for a private project' do
visit project_path(project)
expect(page).to have_content "Page Not Found"
end
it "a pending project member gets a 404 for the project's private group" do
visit group_path(group)
expect(page).to have_content "Page Not Found"
end
it "a project member can see the project's private group once the membership transitions to active" do
membership.activate!
visit group_path(group)
expect(page).to have_content group.name
expect(page).to have_content "Group ID: #{group.id}"
expect(page).to have_content project.name
end
end
context 'with a public project in a public group' do
let_it_be(:group) { create(:group, :public) }
let_it_be(:project) { create(:project, :public, namespace: group) }
before_all do
create(:project_member, :awaiting, :developer, source: project, user: developer)
end
it 'a pending project member sees a public project as if not a member' do
visit project_path(project)
expect(page).to have_content "Project information"
expect(page).not_to have_content "Security & Compliance"
expect(page).not_to have_content "Infrastructure"
end
it "a pending project member sees the project's public group as if not a member" do
visit group_path(group)
expect(page).to have_content "Group ID: #{group.id}"
expect(page).not_to have_content "New project"
expect(page).not_to have_content "Recent activity"
end
end
context 'with a subgroup project' do
let_it_be(:group) { create(:group, :private) }
let_it_be(:subgroup) { create(:group, :private, parent: group) }
let_it_be(:project) { create(:project, :private, namespace: subgroup) }
before_all do
create(:project_member, :awaiting, :developer, source: project, user: developer)
end
it 'a pending project member sees the root group as if not a member' do
visit group_path(group)
expect(page).to have_content "Page Not Found"
end
end
end
...@@ -75,6 +75,36 @@ RSpec.describe ProjectMember do ...@@ -75,6 +75,36 @@ RSpec.describe ProjectMember do
it { is_expected.to eq(false) } it { is_expected.to eq(false) }
end end
describe '#state' do
let!(:group) { create(:group) }
let!(:project) { create(:project, group: group) }
let!(:user) { create(:user) }
describe '#activate!' do
it "refreshes the user's authorized projects" do
membership = create(:project_member, :awaiting, source: project, user: user)
expect(user.authorized_projects).not_to include(project)
membership.activate!
expect(user.authorized_projects.reload).to include(project)
end
end
describe '#wait!' do
it "refreshes the user's authorized projects" do
membership = create(:project_member, source: project, user: user)
expect(user.authorized_projects).to include(project)
membership.wait!
expect(user.authorized_projects.reload).not_to include(project)
end
end
end
describe 'delete protected environment acceses cascadingly' do describe 'delete protected environment acceses cascadingly' do
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
......
...@@ -513,6 +513,8 @@ RSpec.describe Member do ...@@ -513,6 +513,8 @@ RSpec.describe Member do
it { is_expected.not_to include @invited_member } it { is_expected.not_to include @invited_member }
it { is_expected.not_to include @requested_member } it { is_expected.not_to include @requested_member }
it { is_expected.not_to include @member_with_minimal_access } it { is_expected.not_to include @member_with_minimal_access }
it { is_expected.not_to include awaiting_group_member }
it { is_expected.not_to include awaiting_project_member }
end end
describe '.distinct_on_user_with_max_access_level' do describe '.distinct_on_user_with_max_access_level' do
......
...@@ -748,6 +748,30 @@ RSpec.describe API::Internal::Base do ...@@ -748,6 +748,30 @@ RSpec.describe API::Internal::Base do
end end
end end
context 'with a pending membership' do
let_it_be(:project) { create(:project, :repository) }
before_all do
create(:project_member, :awaiting, :developer, source: project, user: user)
end
it 'returns not found for git pull' do
pull(key, project)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response["status"]).to be_falsey
expect(user.reload.last_activity_on).to be_nil
end
it 'returns not found for git push' do
push(key, project)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response["status"]).to be_falsey
expect(user.reload.last_activity_on).to be_nil
end
end
context "custom action" do context "custom action" do
let(:access_checker) { double(Gitlab::GitAccess) } let(:access_checker) { double(Gitlab::GitAccess) }
let(:payload) do let(:payload) do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment