canvas-lms/app/controllers/authentication_audit_api_co...

161 lines
5.5 KiB
Ruby

#
# Copyright (C) 2013 - present 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 Authentications Log
#
# Query audit log of authentication events (logins and logouts).
#
# For each endpoint, a compound document is returned. The primary collection of
# event objects is paginated, ordered by date descending. Secondary collections
# of logins, accounts, page views, and users related to the returned events
# are also included. Refer to the Logins, Accounts, Page Views, and Users APIs
# for descriptions of the objects in those collections.
#
# @model AuthenticationEvent
# {
# "id": "AuthenticationEvent",
# "description": "",
# "properties": {
# "created_at": {
# "description": "timestamp of the event",
# "example": "2012-07-19T15:00:00-06:00",
# "type": "datetime"
# },
# "event_type": {
# "description": "authentication event type ('login' or 'logout')",
# "example": "login",
# "type": "string",
# "allowableValues": {
# "values": [
# "login",
# "logout"
# ]
# }
# },
# "pseudonym_id": {
# "description": "ID of the pseudonym (login) associated with the event",
# "example": 9478,
# "type": "integer"
# },
# "account_id": {
# "description": "ID of the account associated with the event. will match the account_id in the associated pseudonym.",
# "example": 2319,
# "type": "integer"
# },
# "user_id": {
# "description": "ID of the user associated with the event will match the user_id in the associated pseudonym.",
# "example": 362,
# "type": "integer"
# }
# }
# }
#
class AuthenticationAuditApiController < AuditorApiController
include Api::V1::AuthenticationEvent
# @API Query by login.
#
# List authentication events for a given login.
#
# @argument start_time [DateTime]
# The beginning of the time range from which you want events.
#
# @argument end_time [DateTime]
# The end of the time range from which you want events.
#
def for_login
@pseudonym = Pseudonym.active.find(params[:login_id])
if account_visible(@pseudonym.account) || account_visible(Account.site_admin)
events = Auditors::Authentication.for_pseudonym(@pseudonym, query_options)
render_events(events, @pseudonym, api_v1_audit_authentication_login_url(@pseudonym))
else
render_unauthorized_action
end
end
# @API Query by account.
#
# List authentication events for a given account.
#
# @argument start_time [DateTime]
# The beginning of the time range from which you want events.
#
# @argument end_time [DateTime]
# The end of the time range from which you want events.
#
def for_account
@account = api_find(Account.root_accounts.active, params[:account_id])
if account_visible(@account) || account_visible(Account.site_admin)
events = Auditors::Authentication.for_account(@account, query_options)
render_events(events, @account)
else
render_unauthorized_action
end
end
# @API Query by user.
#
# List authentication events for a given user.
#
# @argument start_time [DateTime]
# The beginning of the time range from which you want events.
#
# @argument end_time [DateTime]
# The end of the time range from which you want events.
#
def for_user
@user = api_find(User.active, params[:user_id])
if @user == @current_user || account_visible(Account.site_admin)
events = Auditors::Authentication.for_user(@user, query_options)
render_events(events, @user)
else
accounts = Shard.with_each_shard(@user.associated_shards) do
Account.joins(:pseudonyms).where(:pseudonyms => {
:user_id => @user,
:workflow_state => 'active'
}).to_a
end
visible_accounts = accounts.select{ |a| account_visible(a) }
if visible_accounts == accounts
events = Auditors::Authentication.for_user(@user, query_options)
render_events(events, @user)
elsif visible_accounts.present?
pseudonyms = Shard.partition_by_shard(visible_accounts) do |shard_accounts|
Pseudonym.active.where(user_id: @user, account_id: shard_accounts).to_a
end
events = Auditors::Authentication.for_pseudonyms(pseudonyms, query_options)
render_events(events, @user)
else
render_unauthorized_action
end
end
end
private
def account_visible(account)
account.grants_any_right?(@current_user, :view_statistics, :manage_user_logins)
end
def render_events(events, context, route=nil)
route ||= polymorphic_url([:api_v1, :audit_authentication, context])
events = Api.paginate(events, self, route)
render :json => authentication_events_compound_json(events, @current_user, session)
end
end