Commit c535317b authored by Etienne Baqué's avatar Etienne Baqué

Merge branch 'vij-all-pending-members-api-endpoint' into 'master'

Add a new endpoint for pending members

See merge request gitlab-org/gitlab!75225
parents 2559a9d1 24913c31
...@@ -33,6 +33,13 @@ module EE ...@@ -33,6 +33,13 @@ module EE
scope :with_csv_entity_associations, -> do scope :with_csv_entity_associations, -> do
includes(:user, source: [:route, :parent]) includes(:user, source: [:route, :parent])
end end
scope :awaiting_or_invited_for_group, -> (group) do
awaiting
.or(::Member.invite)
.in_hierarchy(group)
.includes(:user)
end
end end
override :notification_service override :notification_service
......
# frozen_string_literal: true
module API
module Entities
class PendingMember < Grape::Entity
expose :id
expose :user_name, as: :name, if: -> (_) { user.present? }
expose :user_username, as: :username, if: -> (_) { user.present? }
expose :email
expose :web_url, if: -> (_) { user.present? }
expose :invite?, as: :invited
expose :avatar_url do |_|
user&.avatar_url || GravatarService.new.execute(email)
end
expose :approved do |member|
member.active?
end
def email
object.invite_email || object.user.email
end
def web_url
Gitlab::Routing.url_helpers.user_url(user)
end
def user
object.user
end
end
end
end
...@@ -94,6 +94,21 @@ module EE ...@@ -94,6 +94,21 @@ module EE
end end
end end
desc 'Lists all pending members for a group including invited users'
params do
use :pagination
end
get ":id/pending_members" do
group = find_group!(params[:id])
bad_request! unless group.root?
bad_request! unless can?(current_user, :admin_group_member, group)
members = ::Member.awaiting_or_invited_for_group(group)
present paginate(members), with: ::API::Entities::PendingMember
end
desc 'Gets a list of billable users of root group.' do desc 'Gets a list of billable users of root group.' do
success Entities::Member success Entities::Member
end end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe API::Entities::PendingMember do
subject(:pending_member) { described_class.new(member).as_json }
context 'with a user present' do
let(:member) { create(:group_member, :awaiting) }
it 'exposes correct attributes' do
expect(pending_member.keys).to match_array [
:id,
:name,
:username,
:email,
:avatar_url,
:web_url,
:approved,
:invited
]
end
end
context 'with no user present' do
let(:member) { create(:group_member, :invited) }
it 'exposes correct attributes' do
expect(pending_member.keys).to match_array [
:id,
:email,
:avatar_url,
:approved,
:invited
]
end
end
end
...@@ -245,4 +245,23 @@ RSpec.describe Member, type: :model do ...@@ -245,4 +245,23 @@ RSpec.describe Member, type: :model do
end end
end end
end end
describe '.awaiting_or_invited_for_group' do
let_it_be(:active_group_member) { create(:group_member, group: group) }
let_it_be(:awaiting_group_member) { create(:group_member, :awaiting, group: group) }
let_it_be(:awaiting_subgroup_member) { create(:group_member, :awaiting, group: sub_group) }
let_it_be(:awaiting_project_member) { create(:project_member, :awaiting, project: project) }
let_it_be(:awaiting_invited_member) { create(:group_member, :awaiting, :invited, group: group) }
let_it_be(:active_invited_member) { create(:group_member, :invited, group: group) }
it 'returns the correct members' do
expect(described_class.awaiting_or_invited_for_group(group)).to match_array [
awaiting_group_member,
awaiting_subgroup_member,
awaiting_project_member,
awaiting_invited_member,
active_invited_member
]
end
end
end end
...@@ -1103,6 +1103,72 @@ RSpec.describe API::Members do ...@@ -1103,6 +1103,72 @@ RSpec.describe API::Members do
end end
end end
end end
describe 'GET /groups/:id/pending_members' do
let(:url) { "/groups/#{group.id}/pending_members" }
context 'when the current user is not authorized' do
it 'returns a bad request response' do
get api(url, not_an_owner)
expect(response).to have_gitlab_http_status(:bad_request)
end
end
context 'when the current user is authorized' do
let_it_be(:pending_group_member) { create(:group_member, :awaiting, group: group) }
let_it_be(:pending_subgroup_member) { create(:group_member, :awaiting, group: subgroup) }
let_it_be(:pending_project_member) { create(:project_member, :awaiting, project: project) }
let_it_be(:pending_invited_member) { create(:group_member, :awaiting, :invited, group: group) }
it 'returns only pending members' do
create(:group_member, group: group)
get api(url, owner)
expect(json_response.map { |m| m['id'] }).to match_array [
pending_group_member.id,
pending_subgroup_member.id,
pending_project_member.id,
pending_invited_member.id
]
end
it 'includes activated invited members' do
pending_invited_member.activate!
get api(url, owner)
expect(json_response.map { |m| m['id'] }).to match_array [
pending_group_member.id,
pending_subgroup_member.id,
pending_project_member.id,
pending_invited_member.id
]
end
it 'paginates the response' do
get api(url, owner)
expect_paginated_array_response(*[
pending_group_member.id,
pending_subgroup_member.id,
pending_project_member.id,
pending_invited_member.id
])
end
context 'when the group ID is a subgroup' do
let(:url) { "/groups/#{subgroup.id}/pending_members" }
it 'returns a bad request response' do
get api(url, owner)
expect(response).to have_gitlab_http_status(:bad_request)
end
end
end
end
end end
context 'filtering project and group members' do context 'filtering project and group members' 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