add index and delete endpoints to admins api

test plan:
 - render the documentation; ensure the Admins API docs lists
   these endpoints:
   - Make an account admin (existing)
   - Remove account admin (new in this commit)
   - List account admins (new in this commit)
 - exercise these three endpoints by listing, creating, and
   destroying account admins, with and without custom
   roles

fixes #CNVS-3506

Change-Id: Ie4c3c90de2e8891248df352af68a4e5bc9d2fb2a
Reviewed-on: https://gerrit.instructure.com/17497
QA-Review: Adam Phillipps <adam@instructure.com>
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Jeremy Stanley <jeremy@instructure.com>
This commit is contained in:
Jeremy Stanley 2013-02-06 13:44:23 -07:00
parent 73c27a24ab
commit 274a9a3b18
4 changed files with 211 additions and 7 deletions

View File

@ -14,9 +14,26 @@
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# @API Admins
# Manage account role assignments
#
# @object Admin
# {
# // The unique identifier for the account role/user assignment
# "id": 1023,
#
# // The account role assigned. This can be 'AccountAdmin' or a
# // user-defined role created by the Roles API.
# "role": "AccountAdmin",
#
# // The user the role is assigned to. See the Users API for details.
# "user": {
# "id": 8191,
# "name": "A. A. Dinwiddie",
# "login_id": "bursar@uu.example.edu"
# }
# }
class AdminsController < ApplicationController
before_filter :require_user
before_filter :get_context
@ -29,11 +46,11 @@ class AdminsController < ApplicationController
#
# @argument user_id The id of the user to promote.
#
# @argument role [Optional] The user's admin relationship with the
# account will be created with the given role. Defaults to
# 'AccountAdmin'.
# @argument role [Optional] The user's admin relationship with the account will be created with the given role. Defaults to 'AccountAdmin'.
#
# @argument send_confirmation [Optional] [0|1] Send a notification email to the new admin if set to '1'; send no email if set to '0'. Default is '1'.
#
# @returns Admin
def create
if authorized_action(@context, @current_user, :manage_account_memberships)
user = api_find(User, params[:user_id])
@ -41,4 +58,35 @@ class AdminsController < ApplicationController
render :json => admin_json(admin, @current_user, session)
end
end
# @API Remove account admin
#
# Remove the rights associated with an account admin role from a user.
#
# @argument role [Optional] Account role to remove from the user. Defaults to 'AccountAdmin'. Any other account role must be specified explicitly.
#
# @returns Admin
def destroy
if authorized_action(@context, @current_user, :manage_account_memberships)
user = api_find(User, params[:user_id])
role = params[:role] || 'AccountAdmin'
admin = @context.account_users.find_by_user_id_and_membership_type!(user.id, role)
admin.destroy
render :json => admin_json(admin, @current_user, session)
end
end
# @API List account admins
#
# List the admins in the account
#
# @returns [Admin]
def index
if authorized_action(@context, @current_user, :manage_account_memberships)
scope = @context.account_users
route = polymorphic_url([:api_v1, @context, :admins])
admins = Api.paginate(scope, self, route, :order => :id)
render :json => admins.collect{ |admin| admin_json(admin, @current_user, session) }
end
end
end

View File

@ -860,6 +860,8 @@ ActionController::Routing::Routes.draw do |map|
api.with_options(:controller => :admins) do |admins|
admins.post 'accounts/:account_id/admins', :action => :create
admins.delete 'accounts/:account_id/admins/:user_id', :action => :destroy
admins.get 'accounts/:account_id/admins', :action => :index, :path_name => 'account_admins'
end
api.with_options(:controller => :account_authorization_configs) do |authorization_configs|

View File

@ -26,7 +26,8 @@ module Api::V1::Admin
:id => admin.id,
:role => admin.membership_type,
:user => user_json(admin.user, current_user, session)
}
}.tap do |hash|
hash[:status] = 'deleted' if admin.destroyed?
end
end
end

View File

@ -99,5 +99,158 @@ describe "Admins API", :type => :integration do
# Expectation above should pass.
end
end
end
describe "destroy" do
before do
@account = Account.default
@new_user = user_with_managed_pseudonym(:name => 'bad admin', :account => @account, :sis_user_id => 'badmin')
@user = @admin
@base_path = "/api/v1/accounts/#{@account.id}/admins/"
@path = @base_path + "#{@new_user.id}"
@path_opts = { :controller => "admins", :action => "destroy", :format => "json",
:account_id => @account.to_param, :user_id => @new_user.to_param }
end
context "unauthorized caller" do
before do
@user = user :account => @account
end
it "should 401" do
api_call(:delete, @path, @path_opts, {}, {}, :expected_status => 401)
end
end
context "with AccountAdmin membership" do
before do
@au = @account.account_users.create! :user => @new_user
@account.account_users.find_by_user_id(@new_user.id).should_not be_nil
end
it "should remove AccountAdmin membership implicitly" do
json = api_call(:delete, @path, @path_opts)
json['user']['id'].should == @new_user.id
json['id'].should == @au.id
json['role'].should == 'AccountAdmin'
json['status'].should == 'deleted'
@account.account_users.find_by_user_id(@new_user.id).should be_nil
end
it "should remove AccountAdmin membership explicitly" do
api_call(:delete, @path + "?role=AccountAdmin", @path_opts.merge(:role => "AccountAdmin"))
@account.account_users.find_by_user_id(@new_user.id).should be_nil
end
it "should 404 if the user doesn't exist" do
temp_user = User.create!
bad_id = temp_user.to_param
temp_user.destroy!
api_call(:delete, @base_path + bad_id, @path_opts.merge(:user_id => bad_id),
{}, {}, :expected_status => 404)
end
it "should work by sis user id" do
api_call(:delete, @base_path + "sis_user_id:badmin",
@path_opts.merge(:user_id => "sis_user_id:badmin"))
@account.account_users.find_by_user_id(@new_user.id).should be_nil
end
end
context "with custom membership" do
before do
@au = @account.account_users.create! :user => @new_user, :membership_type => 'CustomAdmin'
end
it "should remove a custom membership from a user" do
api_call(:delete, @path + "?role=CustomAdmin", @path_opts.merge(:role => "CustomAdmin"))
@account.account_users.find_by_user_id_and_membership_type(@new_user.id, 'CustomAdmin').should be_nil
end
it "should 404 if the membership type doesn't exist" do
api_call(:delete, @path + "?role=Blah", @path_opts.merge(:role => "Blah"), {}, {}, :expected_status => 404)
@account.account_users.find_by_user_id_and_membership_type(@new_user.id, 'CustomAdmin').should_not be_nil
end
it "should 404 if the membership type isn't specified" do
api_call(:delete, @path, @path_opts, {}, {}, :expected_status => 404)
@account.account_users.find_by_user_id_and_membership_type(@new_user.id, 'CustomAdmin').should_not be_nil
end
end
context "with multiple memberships" do
before do
@au1 = @account.account_users.create! :user => @new_user
@au2 = @account.account_users.create! :user => @new_user, :membership_type => 'CustomAdmin'
end
it "should leave the AccountAdmin membership alone when deleting the custom membership" do
api_call(:delete, @path + "?role=CustomAdmin", @path_opts.merge(:role => "CustomAdmin"))
@account.account_users.find_all_by_user_id(@new_user.id).map(&:membership_type).should == ["AccountAdmin"]
end
it "should leave the custom membership alone when deleting the AccountAdmin membership implicitly" do
api_call(:delete, @path, @path_opts)
@account.account_users.find_all_by_user_id(@new_user.id).map(&:membership_type).should == ["CustomAdmin"]
end
it "should leave the custom membership alone when deleting the AccountAdmin membership explicitly" do
api_call(:delete, @path + "?role=AccountAdmin", @path_opts.merge(:role => "AccountAdmin"))
@account.account_users.find_all_by_user_id(@new_user.id).map(&:membership_type).should == ["CustomAdmin"]
end
end
end
describe "index" do
before do
@account = Account.default
@path = "/api/v1/accounts/#{@account.id}/admins"
@path_opts = { :controller => "admins", :action => "index", :format => "json", :account_id => @account.to_param }
end
context "unauthorized caller" do
before do
@user = user :account => @account
end
it "should 401" do
api_call(:get, @path, @path_opts, {}, {}, :expected_status => 401)
end
end
context "with account users" do
it "should return the correct format" do
json = api_call(:get, @path, @path_opts)
json.should ==[{"id"=>@admin.account_users.first.id,
"role"=>"AccountAdmin",
"user"=>
{"id"=>@admin.id,
"name"=>@admin.name,
"sortable_name"=>@admin.sortable_name,
"short_name"=>@admin.short_name,
"login_id"=>@admin.pseudonym.unique_id}}]
end
it "should paginate" do
4.times do |x|
u = user(:name => "User #{x}", :account => @account)
@account.account_users.create!(:user => u, :membership_type => "MT #{x}")
end
@user = @admin
json = api_call(:get, @path + "?per_page=3", @path_opts.merge(:per_page => '3'))
response.headers['Link'].should match(%r{<http://www.example.com/api/v1/accounts/#{@account.id}/admins\?.*page=2.*>; rel="next",<http://www.example.com/api/v1/accounts/#{@account.id}/admins\?.*page=1.*>; rel="first",<http://www.example.com/api/v1/accounts/#{@account.id}/admins\?.*page=2.*>; rel="last"})
json.map{ |au| { :user => au['user']['name'], :role => au['role'] } }.should == [
{ :user => @admin.name, :role => 'AccountAdmin' },
{ :user => "User 0", :role => "MT 0" },
{ :user => "User 1", :role => "MT 1" }
]
json = api_call(:get, @path + "?per_page=3&page=2", @path_opts.merge(:per_page => '3', :page => '2'))
response.headers['Link'].should match(%r{<http://www.example.com/api/v1/accounts/#{@account.id}/admins\?.*page=1.*>; rel="prev",<http://www.example.com/api/v1/accounts/#{@account.id}/admins\?.*page=1.*>; rel="first",<http://www.example.com/api/v1/accounts/#{@account.id}/admins\?.*page=2.*>; rel="last"})
json.map{ |au| { :user => au['user']['name'], :role => au['role'] } }.should == [
{ :user => "User 2", :role => "MT 2" },
{ :user => "User 3", :role => "MT 3" }
]
end
end
end
end