Skip to content

Commit

Permalink
[spaceship] Add visible_apps relationship to invite users with app pe…
Browse files Browse the repository at this point in the history
…rmissions and fetch user's app permissions (#19053)

* Add visibleApps to User and UserInvitation

* Use visible_apps in create UserInvitation

* Use visible_apps in post_user_invitation

* Get visible apps for invited user

* Use visible_apps in post_user_invitation - fix to use relationships

* Rename visible_apps param to visible_app_ids

* Explain how to use all_apps_visible and visible_app_ids to create user invitation

* Fetch visible apps response fix

* Use all_pages in fetch_visible_apps

* Fetch visible apps for user

* Add tests for get requests, build_params for calls

* Add limit param for get requests

* Add test for post_user_invitation

* Rubocop fixes

* Add limit param to fetch_visible_apps methods

* Code review improvements - rename fetch to get

* Code review improvements - get essential includes for user and user_invitation
  • Loading branch information
lucgrabowski committed Aug 2, 2021
1 parent c07e08d commit 5fb3ff7
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 10 deletions.
20 changes: 17 additions & 3 deletions spaceship/lib/spaceship/connect_api/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class User
attr_accessor :email_vetting_required
attr_accessor :notifications

attr_accessor :visible_apps

attr_mapping({
"username" => "username",
"firstName" => "first_name",
Expand All @@ -27,9 +29,15 @@ class User
"allAppsVisible" => "all_apps_visible",
"provisioningAllowed" => "provisioning_allowed",
"emailVettingRequired" => "email_vetting_required",
"notifications" => "notifications"
"notifications" => "notifications",

"visibleApps" => "visible_apps"
})

ESSENTIAL_INCLUDES = [
"visibleApps"
].join(",")

def self.type
return "users"
end
Expand All @@ -38,16 +46,22 @@ def self.type
# API
#

def self.all(client: nil, filter: {}, includes: nil, limit: nil, sort: nil)
def self.all(client: nil, filter: {}, includes: ESSENTIAL_INCLUDES, limit: nil, sort: nil)
client ||= Spaceship::ConnectAPI
resps = client.get_users(filter: filter, includes: includes).all_pages
return resps.flat_map(&:to_models)
end

def self.find(client: nil, email: nil, includes: nil)
def self.find(client: nil, email: nil, includes: ESSENTIAL_INCLUDES)
client ||= Spaceship::ConnectAPI
return all(client: client, filter: { email: email }, includes: includes)
end

def get_visible_apps(client: nil, limit: nil)
client ||= Spaceship::ConnectAPI
resp = client.get_user_visible_apps(user_id: id, limit: limit)
return resp.to_models
end
end
end
end
31 changes: 26 additions & 5 deletions spaceship/lib/spaceship/connect_api/models/user_invitation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,23 @@ class UserInvitation
attr_accessor :all_apps_visible
attr_accessor :provisioning_allowed

attr_accessor :visible_apps

attr_mapping({
"firstName" => "first_name",
"lastName" => "last_name",
"email" => "email",
"roles" => "roles",
"allAppsVisible" => "all_apps_visible",
"provisioningAllowed" => "provisioning_allowed"
"provisioningAllowed" => "provisioning_allowed",

"visibleApps" => "visible_apps"
})

ESSENTIAL_INCLUDES = [
"visibleApps"
].join(",")

module UserRole
ADMIN = "ADMIN"
FINANCE = "FINANCE"
Expand All @@ -42,26 +50,32 @@ def self.type
# Managing invitations
#

def self.all(client: nil, filter: {}, includes: nil, sort: nil)
def self.all(client: nil, filter: {}, includes: ESSENTIAL_INCLUDES, sort: nil)
client ||= Spaceship::ConnectAPI
resps = client.get_user_invitations(filter: filter, includes: includes, sort: sort).all_pages
return resps.flat_map(&:to_models)
end

def self.find(client: nil, email: nil, includes: nil)
def self.find(client: nil, email: nil, includes: ESSENTIAL_INCLUDES)
client ||= Spaceship::ConnectAPI
return all(client: client, filter: { email: email }, includes: includes)
end

def self.create(client: nil, email: nil, first_name: nil, last_name: nil, roles: [], provisioning_allowed: nil, all_apps_visible: nil)
# Create and post user invitation
# App Store Connect allows for the following combinations of `all_apps_visible` and `visible_app_ids`:
# - if `all_apps_visible` is `nil`, you don't have to provide values for `visible_app_ids`
# - if `all_apps_visible` is true, you must provide values for `visible_app_ids`.
# - if `all_apps_visible` is false, you must not provide values for `visible_app_ids`.
def self.create(client: nil, email: nil, first_name: nil, last_name: nil, roles: [], provisioning_allowed: nil, all_apps_visible: nil, visible_app_ids: [])
client ||= Spaceship::ConnectAPI
resp = client.post_user_invitation(
email: email,
first_name: first_name,
last_name: last_name,
roles: roles,
provisioning_allowed: provisioning_allowed,
all_apps_visible: all_apps_visible
all_apps_visible: all_apps_visible,
visible_app_ids: visible_app_ids
)
return resp.to_models.first
end
Expand All @@ -70,6 +84,13 @@ def delete!(client: nil)
client ||= Spaceship::ConnectAPI
client.delete_user_invitation(user_invitation_id: id)
end

# Get visible apps for invited user
def get_visible_apps(client: nil, limit: nil)
client ||= Spaceship::ConnectAPI
resp = client.get_user_invitation_visible_apps(user_invitation_id: id, limit: limit)
return resp.to_models
end
end
end
end
26 changes: 24 additions & 2 deletions spaceship/lib/spaceship/connect_api/users/users.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,24 @@ def add_user_visible_apps(user_id: nil, app_ids: nil)
users_request_client.post("users/#{user_id}/relationships/visibleApps", body)
end

# Get app permissions for user
def get_user_visible_apps(user_id: id, limit: nil)
params = users_request_client.build_params(filter: {}, includes: nil, limit: limit, sort: nil)
users_request_client.get("users/#{user_id}/visibleApps", params)
end

#
# invitations (invited users)
#

# Get all invited users (not yet accepted)
# Get all invited users
def get_user_invitations(filter: {}, includes: nil, limit: nil, sort: nil)
params = users_request_client.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
users_request_client.get("userInvitations", params)
end

# Invite new users to App Store Connect
def post_user_invitation(email: nil, first_name: nil, last_name: nil, roles: [], provisioning_allowed: nil, all_apps_visible: nil)
def post_user_invitation(email: nil, first_name: nil, last_name: nil, roles: [], provisioning_allowed: nil, all_apps_visible: nil, visible_app_ids: [])
body = {
data: {
type: "userInvitations",
Expand All @@ -64,6 +70,16 @@ def post_user_invitation(email: nil, first_name: nil, last_name: nil, roles: [],
roles: roles,
provisioningAllowed: provisioning_allowed,
allAppsVisible: all_apps_visible
},
relationships: {
visibleApps: {
data: visible_app_ids.map do |id|
{
id: id,
type: "apps"
}
end
}
}
}
}
Expand All @@ -74,6 +90,12 @@ def post_user_invitation(email: nil, first_name: nil, last_name: nil, roles: [],
def delete_user_invitation(user_invitation_id: nil)
users_request_client.delete("userInvitations/#{user_invitation_id}")
end

# Get all app permissions for invited user
def get_user_invitation_visible_apps(user_invitation_id: id, limit: nil)
params = users_request_client.build_params(filter: {}, includes: nil, limit: limit, sort: nil)
users_request_client.get("userInvitations/#{user_invitation_id}/visibleApps", params)
end
end
end
end
Expand Down
75 changes: 75 additions & 0 deletions spaceship/spec/connect_api/users/user_client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,81 @@ def test_request_body(url, body)
client.get_users
end
end

context 'get_user_visible_apps' do
let(:user_id) { "42" }
let(:path) { "users/#{user_id}/visibleApps" }

it 'succeeds' do
params = {}
req_mock = test_request_params(path, params)
expect(client).to receive(:request).with(:get).and_yield(req_mock).and_return(req_mock)
client.get_user_visible_apps(user_id: user_id)
end
end
end

describe "user_invitations" do
context 'post_user_invitation' do
let(:path) { "userInvitations" }
let(:attributes) {
{
email: "test@example.com",
firstName: "Firstname",
lastName: "Lastname",
roles: [],
provisioningAllowed: true,
allAppsVisible: false
}
}
let(:visible_app_ids) { ["123", "456"] }
let(:body) do
{
data: {
type: "userInvitations",
attributes: attributes,
relationships: {
visibleApps: {
data: visible_app_ids.map do |id|
{
id: id,
type: "apps"
}
end
}
}
}
}
end

it 'succeeds' do
url = path
req_mock = test_request_body(url, body)

expect(client).to receive(:request).with(:post).and_yield(req_mock).and_return(req_mock)
client.post_user_invitation(
email: "test@example.com",
first_name: "Firstname",
last_name: "Lastname",
roles: [],
provisioning_allowed: true,
all_apps_visible: false,
visible_app_ids: ["123", "456"]
)
end
end

context 'get_user_invitation_visible_apps' do
let(:invitation_id) { "42" }
let(:path) { "userInvitations/#{invitation_id}/visibleApps" }

it 'succeeds' do
params = {}
req_mock = test_request_params(path, params)
expect(client).to receive(:request).with(:get).and_yield(req_mock).and_return(req_mock)
client.get_user_invitation_visible_apps(user_invitation_id: invitation_id)
end
end
end
end
end

0 comments on commit 5fb3ff7

Please sign in to comment.