Add support for organization :id in or organizations routes (#20244)

This commit is contained in:
Daniel M Brasil 2023-10-25 18:38:45 -03:00 committed by GitHub
parent 8963e185f8
commit 74cc4ac39e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 149 additions and 104 deletions

View file

@ -73,7 +73,9 @@ module Api
def find_organization
# Looking up via id_or_slug parameter since both types of lookup are handled in
# the v1 show route
@organization = Organization.find_by!(username: params[:organization_id_or_slug])
@organization = Organization.find_by(id: params[:organization_id_or_slug]) ||
Organization.find_by(username: params[:organization_id_or_slug])
raise ActiveRecord::RecordNotFound unless @organization
end
end
end

View file

@ -41,7 +41,7 @@ RSpec.describe "Api::V1::Docs::Organizations" do
end
end
path "/api/organizations/{username}/users" do
path "/api/organizations/{organization_id_or_username}/users" do
get "Organization's users" do
tags "organizations", "users"
security []
@ -50,12 +50,20 @@ RSpec.describe "Api::V1::Docs::Organizations" do
It supports pagination, each page will contain `30` users by default."
operationId "getOrgUsers"
produces "application/json"
parameter name: :username, in: :path, type: :string, required: true
parameter name: :organization_id_or_username, in: :path, type: :string, required: true
parameter "$ref": "#/components/parameters/pageParam"
parameter "$ref": "#/components/parameters/perPageParam30to1000"
response "200", "An Organization's users" do
let(:username) { organization.username }
response "200", "An Organization's users (with username)" do
let(:organization_id_or_username) { organization.username }
schema type: :array,
items: { "$ref": "#/components/schemas/User" }
add_examples
run_test!
end
response "200", "An Organization's users (with ID)" do
let(:organization_id_or_username) { organization.id }
schema type: :array,
items: { "$ref": "#/components/schemas/User" }
add_examples
@ -63,14 +71,14 @@ It supports pagination, each page will contain `30` users by default."
end
response "404", "Not Found" do
let(:username) { "non-existent-username" }
let(:organization_id_or_username) { "non-existent-id-or-username" }
add_examples
run_test!
end
end
end
path "/api/organizations/{username}/articles" do
path "/api/organizations/{organization_id_or_username}/articles" do
get "Organization's Articles" do
tags "organizations", "articles"
security []
@ -79,12 +87,20 @@ It supports pagination, each page will contain `30` users by default."
It supports pagination, each page will contain `30` users by default."
operationId "getOrgArticles"
produces "application/json"
parameter name: :username, in: :path, type: :string, required: true
parameter name: :organization_id_or_username, in: :path, type: :string, required: true
parameter "$ref": "#/components/parameters/pageParam"
parameter "$ref": "#/components/parameters/perPageParam30to1000"
response "200", "An Organization's Articles" do
let(:username) { organization.username }
response "200", "An Organization's Articles (with username)" do
let(:organization_id_or_username) { organization.username }
schema type: :array,
items: { "$ref": "#/components/schemas/ArticleIndex" }
add_examples
run_test!
end
response "200", "An Organization's Articles (with ID)" do
let(:organization_id_or_username) { organization.id }
schema type: :array,
items: { "$ref": "#/components/schemas/ArticleIndex" }
add_examples
@ -92,7 +108,7 @@ It supports pagination, each page will contain `30` users by default."
end
response "404", "Not Found" do
let(:username) { "non-existent-username" }
let(:organization_id_or_username) { "non-existent-username" }
add_examples
run_test!
end

View file

@ -243,61 +243,74 @@ RSpec.describe "Api::V1::Organizations" do
end
end
describe "GET /api/organizations/:username/users" do
describe "GET /api/organizations/:organization_id_or_slug/users" do
let!(:org_user) { create(:user, :org_member) }
let(:organization) { org_user.organizations.first }
it "returns 404 if the organizations username is not found" do
get "/api/organizations/invalid-username/users", headers: headers
expect(response).to have_http_status(:not_found)
end
it "supports pagination" do
create(:organization_membership, user: create(:user), organization: organization)
get api_organization_users_path(organization.username), params: { page: 1, per_page: 1 }, headers: headers
expect(response.parsed_body.length).to eq(1)
get api_organization_users_path(organization.username), params: { page: 2, per_page: 1 }, headers: headers
expect(response.parsed_body.length).to eq(1)
get api_organization_users_path(organization.username), params: { page: 3, per_page: 1 }, headers: headers
expect(response.parsed_body.length).to eq(0)
end
it "respects API_PER_PAGE_MAX limit set in ENV variable" do
allow(ApplicationConfig).to receive(:[]).and_return(nil)
allow(ApplicationConfig).to receive(:[]).with("APP_PROTOCOL").and_return("http://")
allow(ApplicationConfig).to receive(:[]).with("API_PER_PAGE_MAX").and_return(2)
create(:organization_membership, user: create(:user), organization: organization)
create(:organization_membership, user: create(:user), organization: organization)
create(:organization_membership, user: create(:user), organization: organization)
get api_organization_users_path(organization.username), params: { per_page: 10 }
expect(response.parsed_body.count).to eq(2)
end
it "returns the correct json representation of the organizations users", :aggregate_failures do
get api_organization_users_path(organization.username), headers: headers
response_org_users = response.parsed_body.first
expect(response_org_users["type_of"]).to eq("user")
%w[id username name twitter_username github_username].each do |attr|
expect(response_org_users[attr]).to eq(org_user.public_send(attr))
shared_examples "a lookup by ID or slug" do
it "returns 404 if the organization is not found" do
get "/api/organizations/invalid-id-or-username/users", headers: headers
expect(response).to have_http_status(:not_found)
end
org_user_profile = org_user.profile
%w[summary location website_url].each do |attr|
expect(response_org_users[attr]).to eq(org_user_profile.public_send(attr))
it "supports pagination" do
create(:organization_membership, user: create(:user), organization: organization)
get api_organization_users_path(id_or_slug), params: { page: 1, per_page: 1 }, headers: headers
expect(response.parsed_body.length).to eq(1)
get api_organization_users_path(id_or_slug), params: { page: 2, per_page: 1 }, headers: headers
expect(response.parsed_body.length).to eq(1)
get api_organization_users_path(id_or_slug), params: { page: 3, per_page: 1 }, headers: headers
expect(response.parsed_body.length).to eq(0)
end
expect(response_org_users["joined_at"]).to eq(org_user.created_at.strftime("%b %e, %Y"))
expect(response_org_users["profile_image"]).to eq(org_user.profile_image_url_for(length: 320))
it "respects API_PER_PAGE_MAX limit set in ENV variable" do
allow(ApplicationConfig).to receive(:[]).and_return(nil)
allow(ApplicationConfig).to receive(:[]).with("APP_PROTOCOL").and_return("http://")
allow(ApplicationConfig).to receive(:[]).with("API_PER_PAGE_MAX").and_return(2)
expect(response_org_users.key?("email")).to be false
create(:organization_membership, user: create(:user), organization: organization)
create(:organization_membership, user: create(:user), organization: organization)
create(:organization_membership, user: create(:user), organization: organization)
get api_organization_users_path(id_or_slug), params: { per_page: 10 }
expect(response.parsed_body.count).to eq(2)
end
it "returns the correct json representation of the organizations users", :aggregate_failures do
get api_organization_users_path(id_or_slug), headers: headers
response_org_users = response.parsed_body.first
expect(response_org_users["type_of"]).to eq("user")
%w[id username name twitter_username github_username].each do |attr|
expect(response_org_users[attr]).to eq(org_user.public_send(attr))
end
org_user_profile = org_user.profile
%w[summary location website_url].each do |attr|
expect(response_org_users[attr]).to eq(org_user_profile.public_send(attr))
end
expect(response_org_users["joined_at"]).to eq(org_user.created_at.strftime("%b %e, %Y"))
expect(response_org_users["profile_image"]).to eq(org_user.profile_image_url_for(length: 320))
expect(response_org_users.key?("email")).to be false
end
end
context "when looking up by the organization's id" do
let(:id_or_slug) { organization.id }
it_behaves_like "a lookup by ID or slug"
end
context "when looking up by the organization's username" do
let(:id_or_slug) { organization.username }
it_behaves_like "a lookup by ID or slug"
end
end
@ -365,67 +378,81 @@ RSpec.describe "Api::V1::Organizations" do
end
end
describe "GET /api/organizations/:username/articles" do
describe "GET /api/organizations/:organization_id_or_slug/articles" do
let(:org_user) { create(:user, :org_member) }
let(:organization) { org_user.organizations.first }
let!(:article) { create(:article, user: org_user, organization: organization) }
it "returns 404 if the organizations articles is not found" do
get "/api/organizations/invalid-username/articles", headers: headers
expect(response).to have_http_status(:not_found)
end
it "supports pagination" do
create(:article, organization: organization)
get api_organization_articles_path(organization.username),
params: { page: 1, per_page: 1 },
headers: headers
expect(response.parsed_body.length).to eq(1)
get api_organization_articles_path(organization.username),
params: { page: 2, per_page: 1 },
headers: headers
expect(response.parsed_body.length).to eq(1)
get api_organization_articles_path(organization.username),
params: { page: 3, per_page: 1 },
headers: headers
expect(response.parsed_body.length).to eq(0)
end
it "returns the correct json representation of the organizations articles", :aggregate_failures do
get api_organization_articles_path(organization.username), headers: headers
response_article = response.parsed_body.first
expect(response_article["type_of"]).to eq("article")
%w[id title slug description path public_reactions_count
positive_reactions_count comments_count published_timestamp].each do |attr|
expect(response_article[attr]).to eq(article.public_send(attr))
shared_examples "a lookup by ID or slug" do
it "returns 404 if the organization is not found" do
get "/api/organizations/invalid-id-or-username/articles", headers: headers
expect(response).to have_http_status(:not_found)
end
expect(response_article["tag_list"]).to match_array(article.tag_list)
it "supports pagination" do
create(:article, organization: organization)
%w[name username twitter_username github_username].each do |attr|
expect(response_article["user"][attr]).to eq(org_user.public_send(attr))
get api_organization_articles_path(id_or_slug),
params: { page: 1, per_page: 1 },
headers: headers
expect(response.parsed_body.length).to eq(1)
get api_organization_articles_path(id_or_slug),
params: { page: 2, per_page: 1 },
headers: headers
expect(response.parsed_body.length).to eq(1)
get api_organization_articles_path(id_or_slug),
params: { page: 3, per_page: 1 },
headers: headers
expect(response.parsed_body.length).to eq(0)
end
expect(response_article["user"]["website_url"]).to eq(org_user.profile.website_url)
it "returns the correct json representation of the organizations articles", :aggregate_failures do
get api_organization_articles_path(id_or_slug), headers: headers
response_article = response.parsed_body.first
expect(response_article["type_of"]).to eq("article")
%w[name username slug].each do |attr|
expect(response_article["organization"][attr]).to eq(organization.public_send(attr))
%w[id title slug description path public_reactions_count
positive_reactions_count comments_count published_timestamp].each do |attr|
expect(response_article[attr]).to eq(article.public_send(attr))
end
expect(response_article["tag_list"]).to match_array(article.tag_list)
%w[name username twitter_username github_username].each do |attr|
expect(response_article["user"][attr]).to eq(org_user.public_send(attr))
end
expect(response_article["user"]["website_url"]).to eq(org_user.profile.website_url)
%w[name username slug].each do |attr|
expect(response_article["organization"][attr]).to eq(organization.public_send(attr))
end
end
it "respects API_PER_PAGE_MAX limit set in ENV variable" do
allow(ApplicationConfig).to receive(:[]).and_return(nil)
allow(ApplicationConfig).to receive(:[]).with("APP_PROTOCOL").and_return("http://")
allow(ApplicationConfig).to receive(:[]).with("API_PER_PAGE_MAX").and_return(2)
create_list(:article, 3, organization: organization)
get api_organization_articles_path(id_or_slug), params: { per_page: 10 }, headers: headers
expect(response.parsed_body.count).to eq(2)
end
end
it "respects API_PER_PAGE_MAX limit set in ENV variable" do
allow(ApplicationConfig).to receive(:[]).and_return(nil)
allow(ApplicationConfig).to receive(:[]).with("APP_PROTOCOL").and_return("http://")
allow(ApplicationConfig).to receive(:[]).with("API_PER_PAGE_MAX").and_return(2)
context "when looking up by the organization's ID" do
let(:id_or_slug) { organization.id }
create_list(:article, 3, organization: organization)
it_behaves_like "a lookup by ID or slug"
end
get api_organization_articles_path(organization.username), params: { per_page: 10 }, headers: headers
expect(response.parsed_body.count).to eq(2)
context "when looking up by the organization's username" do
let(:id_or_slug) { organization.username }
it_behaves_like "a lookup by ID or slug"
end
end
end