canvas-lms/app/controllers/user_observees_controller.rb

199 lines
6.0 KiB
Ruby

#
# Copyright (C) 2011 - 2014 Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# 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 User Observees
# API for accessing information about the users a user is observing.
class UserObserveesController < ApplicationController
before_filter :require_user
before_filter :self_or_admin_permission_check, only: [:index, :create, :show]
before_filter :admin_permission_check, except: [:index, :create, :show]
# @API List observees
#
# List the users that the given user is observing.
#
# *Note:* all users are allowed to list their own observees. Administrators can list
# other users' observees.
#
# @example_request
# curl https://<canvas>/api/v1/users/<user_id>/observees \
# -X GET \
# -H 'Authorization: Bearer <token>'
#
# @returns [User]
def index
observed_users = user.observed_users.order_by_sortable_name
observed_users = Api.paginate(observed_users, self, api_v1_user_observees_url)
render json: users_json(observed_users, @current_user, session)
end
# @API Add an observee with credentials
#
# Register the given user to observe another user, given the observee's credentials.
#
# *Note:* all users are allowed to add their own observees, given the observee's
# credentials are provided. Administrators can add observees given credentials or
# the {api:UserObserveesController#update observee's id}.
#
# @argument observee[unique_id] [Required, String]
# The login id for the user to observe.
#
# @argument observee[password] [Required, String]
# The password for the user to observe.
#
# @example_request
# curl https://<canvas>/api/v1/users/<user_id>/observees \
# -X POST \
# -H 'Authorization: Bearer <token>' \
# -F 'observee[unique_id]=UNIQUE_ID' \
# -F 'observee[password]=PASSWORD'
#
# @returns User
def create
observee_pseudonym = Pseudonym.authenticate(params[:observee] || {}, [@domain_root_account.id] + @domain_root_account.trusted_account_ids)
observee_user = observee_pseudonym.user if observee_pseudonym && common_accounts_for(user, observee_pseudonym.user).present?
if observee_user
add_observee(observee_user)
render json: user_json(observee_user, @current_user, session)
else
render json: {errors: [{'message' => 'Invalid credentials provided.'}]}, status: :unauthorized
end
end
# @API Show an observee
#
# Gets information about an observed user.
#
# *Note:* all users are allowed to view their own observees.
#
# @example_request
# curl https://<canvas>/api/v1/users/<user_id>/observees/<observee_id> \
# -X GET \
# -H 'Authorization: Bearer <token>'
#
# @returns User
def show
raise ActiveRecord::RecordNotFound unless has_observee?(observee)
render json: user_json(observee, @current_user, session)
end
# @API Add an observee
#
# Registers a user as being observed by the given user.
#
# @example_request
# curl https://<canvas>/api/v1/users/<user_id>/observees/<observee_id> \
# -X PUT \
# -H 'Authorization: Bearer <token>'
#
# @returns User
def update
raise ActiveRecord::RecordNotFound unless can_manage_observers_for?(user, observee)
add_observee(observee)
render json: user_json(observee, @current_user, session)
end
# @API Remove an observee
#
# Unregisters a user as being observed by the given user.
#
# @example_request
# curl https://<canvas>/api/v1/users/<user_id>/observees/<observee_id> \
# -X DELETE \
# -H 'Authorization: Bearer <token>'
#
# @returns User
def destroy
raise ActiveRecord::RecordNotFound unless has_observee?(observee)
remove_observee(observee)
render json: user_json(observee, @current_user, session)
end
private
def user
@user ||= params[:user_id].nil? ? @current_user : api_find(User, params[:user_id])
end
def observee
@observee ||= api_find(User, params[:observee_id])
end
def add_observee(observee)
unless has_observee?(observee)
user.user_observees.create! do |uo|
uo.user_id = observee.id
end
user.touch
end
end
def remove_observee(observee)
user.user_observees.where(user_id: observee).destroy_all
user.touch
end
def has_observee?(observee)
user.user_observees.where(user_id: observee).exists?
end
def self_or_admin_permission_check
return true if user == @current_user
admin_permission_check
end
def admin_permission_check
return true if can_manage = can_manage_observers_for?(user)
if can_manage.nil?
raise ActiveRecord::RecordNotFound
else
render_unauthorized_action
end
end
def common_accounts_for(*users)
shards = users.map(&:associated_shards).reduce(:&)
Shard.with_each_shard(shards) do
user_ids = users.map(&:id)
Account.where(id: UserAccountAssociation
.joins(:account).where(accounts: {parent_account_id: nil})
.where(user_id: user_ids)
.group(:account_id)
.having("count(*) = #{user_ids.length}") # user => account is unique for user_account_associations
.select(:account_id)
)
end
end
def can_manage_observers_for?(*users)
matching_accounts = common_accounts_for(*users)
return nil if matching_accounts.empty?
matching_accounts.any? do |a|
return true if a.grants_right?(@current_user, :manage_user_observers)
end
end
end