API: Endpoint to get an organization's users (#11514)
* add tests * add route * add users action to organizations controller * add jbuilder file * update api docs * add recource routes * make updates to organizations controller * remove org_users from api docs * update spec * add users show jbuilder * bug fix for user show
This commit is contained in:
parent
d5546d6d6b
commit
de3d62bc40
7 changed files with 151 additions and 25 deletions
|
|
@ -1,15 +1,37 @@
|
|||
module Api
|
||||
module V0
|
||||
class OrganizationsController < ApiController
|
||||
before_action :find_organization, only: %i[users]
|
||||
|
||||
SHOW_ATTRIBUTES_FOR_SERIALIZATION = %i[
|
||||
username name summary twitter_username github_username url
|
||||
location created_at profile_image tech_stack tag_line story
|
||||
].freeze
|
||||
private_constant :SHOW_ATTRIBUTES_FOR_SERIALIZATION
|
||||
|
||||
USERS_FOR_SERIALIZATION = %i[
|
||||
id username name twitter_username github_username
|
||||
profile_image website_url location summary created_at
|
||||
].freeze
|
||||
private_constant :USERS_FOR_SERIALIZATION
|
||||
|
||||
def show
|
||||
@organization = Organization.select(SHOW_ATTRIBUTES_FOR_SERIALIZATION)
|
||||
.find_by!(username: params[:org_username])
|
||||
.find_by!(username: params[:username])
|
||||
end
|
||||
|
||||
def users
|
||||
per_page = (params[:per_page] || 30).to_i
|
||||
num = [per_page, 1000].min
|
||||
page = params[:page] || 1
|
||||
|
||||
@users = @organization.users.select(USERS_FOR_SERIALIZATION).page(page).per(num)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_organization
|
||||
@organization = Organization.find_by!(username: params[:organization_username])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
3
app/views/api/v0/organizations/users.json.jbuilder
Normal file
3
app/views/api/v0/organizations/users.json.jbuilder
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
json.array! @users do |user|
|
||||
json.partial! "api/v0/shared/user_show", user: user
|
||||
end
|
||||
16
app/views/api/v0/shared/_user_show.json.jbuilder
Normal file
16
app/views/api/v0/shared/_user_show.json.jbuilder
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
json.type_of "user"
|
||||
|
||||
json.extract!(
|
||||
user,
|
||||
:id,
|
||||
:username,
|
||||
:name,
|
||||
:summary,
|
||||
:twitter_username,
|
||||
:github_username,
|
||||
:website_url,
|
||||
:location,
|
||||
)
|
||||
|
||||
json.joined_at user.created_at.strftime("%b %e, %Y")
|
||||
json.profile_image Images::Profile.call(user.profile_image_url, length: 320)
|
||||
|
|
@ -1,16 +1 @@
|
|||
json.type_of "user"
|
||||
|
||||
json.extract!(
|
||||
@user,
|
||||
:id,
|
||||
:username,
|
||||
:name,
|
||||
:summary,
|
||||
:twitter_username,
|
||||
:github_username,
|
||||
:website_url,
|
||||
:location,
|
||||
)
|
||||
|
||||
json.joined_at @user.created_at.strftime("%b %e, %Y")
|
||||
json.profile_image Images::Profile.call(@user.profile_image_url, length: 320)
|
||||
json.partial! "api/v0/shared/user_show", user: @user
|
||||
|
|
|
|||
|
|
@ -203,10 +203,8 @@ Rails.application.routes.draw do
|
|||
end
|
||||
|
||||
resources :profile_images, only: %i[show], param: :username
|
||||
resources :organizations, only: [] do
|
||||
collection do
|
||||
get "/:org_username", to: "organizations#show"
|
||||
end
|
||||
resources :organizations, only: [:show], param: :username do
|
||||
resources :users, only: [:index], to: "organizations#users"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ info:
|
|||
Dates and date times, unless otherwise specified, must be in
|
||||
the [RFC 3339](https://tools.ietf.org/html/rfc3339) format.
|
||||
|
||||
version: "0.9.2"
|
||||
version: "0.9.3"
|
||||
termsOfService: https://dev.to/terms
|
||||
contact:
|
||||
name: DEV Team
|
||||
|
|
@ -1683,6 +1683,20 @@ components:
|
|||
joined_at: Jan 1, 2017
|
||||
profile_image: https://res.cloudinary.com/...jpeg
|
||||
|
||||
Users:
|
||||
value:
|
||||
- type_of: user
|
||||
id: 1234
|
||||
username: bob
|
||||
name: bob
|
||||
summary: Hello, world
|
||||
twitter_username: bob
|
||||
github_username: bob
|
||||
website_url:
|
||||
location: New York
|
||||
joined_at: Jan 1, 2017
|
||||
profile_image: https://res.cloudinary.com/...jpeg
|
||||
|
||||
WebhookCreate:
|
||||
value:
|
||||
webhook_endpoint:
|
||||
|
|
@ -2986,7 +3000,7 @@ paths:
|
|||
source: |
|
||||
curl -H "api-key: API_KEY" https://dev.to/api/readinglist
|
||||
|
||||
/organizations/{org_username}:
|
||||
/organizations/{username}:
|
||||
get:
|
||||
operationId: getOrganization
|
||||
summary: An organization
|
||||
|
|
@ -2995,7 +3009,7 @@ paths:
|
|||
tags:
|
||||
- organizations
|
||||
parameters:
|
||||
- name: org_username
|
||||
- name: username
|
||||
in: path
|
||||
required: true
|
||||
description: |
|
||||
|
|
@ -3028,6 +3042,54 @@ paths:
|
|||
source: |
|
||||
curl https://dev.to/api/organizations/ecorp
|
||||
|
||||
/organizations/{username}/users:
|
||||
get:
|
||||
operationId: getOrgUsers
|
||||
summary: Organization's users
|
||||
description: |
|
||||
This endpoint allows the client to retrieve a list of users belonging to the organization
|
||||
|
||||
It supports pagination, each page will contain `30` users by default.
|
||||
tags:
|
||||
- organizations
|
||||
parameters:
|
||||
- name: username
|
||||
in: path
|
||||
required: true
|
||||
description: |
|
||||
Username of the organization
|
||||
schema:
|
||||
type: string
|
||||
example: "ecorp"
|
||||
- $ref: '#/components/parameters/pageParam'
|
||||
- $ref: '#/components/parameters/perPageParam30to1000'
|
||||
responses:
|
||||
"200":
|
||||
description: A list of users belonging to the organization
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/User"
|
||||
examples:
|
||||
user-success:
|
||||
$ref: "#/components/examples/Users"
|
||||
"404":
|
||||
description: Resource not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/APIError"
|
||||
examples:
|
||||
user-not-found:
|
||||
$ref: "#/components/examples/ErrorNotFound"
|
||||
x-code-samples:
|
||||
- lang: Shell
|
||||
label: curl
|
||||
source: |
|
||||
curl https://dev.to/api/organizations/ecorp/users
|
||||
|
||||
/podcast_episodes:
|
||||
get:
|
||||
operationId: getPodcastEpisodes
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ RSpec.describe "Api::V0::Organizations", type: :request do
|
|||
end
|
||||
|
||||
it "returns the correct json representation of the organization", :aggregate_failures do
|
||||
get "/api/organizations/#{organization.username}"
|
||||
get api_organization_path(organization.username)
|
||||
|
||||
response_organization = response.parsed_body
|
||||
|
||||
|
|
@ -25,4 +25,44 @@ RSpec.describe "Api::V0::Organizations", type: :request do
|
|||
expect(response_organization["joined_at"]).to eq(organization.created_at.utc.iso8601)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/organizations/:username/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"
|
||||
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 }
|
||||
expect(response.parsed_body.length).to eq(1)
|
||||
|
||||
get api_organization_users_path(organization.username), params: { page: 2, per_page: 1 }
|
||||
expect(response.parsed_body.length).to eq(1)
|
||||
|
||||
get api_organization_users_path(organization.username), params: { page: 3, per_page: 1 }
|
||||
expect(response.parsed_body.length).to eq(0)
|
||||
end
|
||||
|
||||
it "returns the correct json representation of the organizations users", :aggregate_failures do
|
||||
get api_organization_users_path(organization.username)
|
||||
|
||||
response_org_users = response.parsed_body.first
|
||||
|
||||
expect(response_org_users["type_of"]).to eq("user")
|
||||
|
||||
%w[
|
||||
id username name summary twitter_username github_username website_url location
|
||||
].each do |attr|
|
||||
expect(response_org_users[attr]).to eq(org_user.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(Images::Profile.call(org_user.profile_image_url, length: 320))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue