add user access logging to various endpoints

test plan:
* with cassandra and page views enabled, should be able to
log user access to:
 - course home
 - course modules index
 - outcomes index,
 - assignments index
 - pages index
 - external urls
 - external tools tools

(and be able to view them in the user access report)

* also confirm that visiting the discussions index
does not register multiple views when visiting once

closes #CNVS-15321

Change-Id: I43329b1764cdf0c313f548f6aefa3af26c03f300
Reviewed-on: https://gerrit.instructure.com/42075
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Jeremy Stanley <jeremy@instructure.com>
QA-Review: Jahnavi Yetukuri <jyetukuri@instructure.com>
Product-Review: Hilary Scharton <hilary@instructure.com>
This commit is contained in:
James Williams 2014-10-01 07:23:18 -06:00 committed by Jeremy Stanley
parent d1e8717120
commit 61c51c7724
11 changed files with 30 additions and 4 deletions

View File

@ -1180,6 +1180,7 @@ class ApplicationController < ActionController::Base
elsif tag.content_type == 'ExternalUrl'
@tag = tag
@module = tag.context_module
log_asset_access(@tag, "external_urls", "external_urls")
tag.context_module_action(@current_user, :read) unless tag.locked_for? @current_user
render :template => 'context_modules/url_show'
elsif tag.content_type == 'ContextExternalTool'
@ -1200,6 +1201,7 @@ class ApplicationController < ActionController::Base
redirect_to named_context_url(context, error_redirect_symbol)
else
return unless require_user
log_asset_access(@tool, "external_tools", "external_tools")
@opaque_id = @tool.opaque_identifier_for(@tag)
@lti_launch = Lti::Launch.new

View File

@ -36,6 +36,8 @@ class AssignmentsController < ApplicationController
if authorized_action(@context, @current_user, :read)
return unless tab_enabled?(@context.class::TAB_ASSIGNMENTS)
log_asset_access("assignments:#{@context.asset_string}", 'assignments', 'other')
add_crumb(t('#crumbs.assignments', "Assignments"), named_context_url(@context, :context_assignments_url))
# It'd be nice to do this as an after_create, but it's not that simple

View File

@ -37,6 +37,7 @@ class ContextModulesController < ApplicationController
def index
if authorized_action(@context, @current_user, :read)
log_asset_access("modules:#{@context.asset_string}", "modules", "other")
load_modules
if @context.grants_right?(@current_user, session, :participate_as_student)
return unless tab_enabled?(@context.class::TAB_MODULES)

View File

@ -1360,6 +1360,8 @@ class CoursesController < ApplicationController
@context_enrollment ||= @pending_enrollment
if is_authorized_action?(@context, @current_user, :read)
log_asset_access("home:#{@context.asset_string}", "home", "other")
check_incomplete_registration
add_crumb(@context.short_name, url_for(@context), :id => "crumb_#{@context.asset_string}")

View File

@ -250,8 +250,6 @@ class DiscussionTopicsController < ApplicationController
return unless authorized_action(@context.discussion_topics.scoped.new, @current_user, :read)
return child_topic if is_child_topic?
log_asset_access("topics:#{@context.asset_string}", 'topics', 'other')
scope = if params[:only_announcements]
@context.active_announcements
else
@ -293,6 +291,8 @@ class DiscussionTopicsController < ApplicationController
respond_to do |format|
format.html do
log_asset_access("topics:#{@context.asset_string}", 'topics', 'other')
@active_tab = 'discussions'
add_crumb(t('#crumbs.discussions', 'Discussions'),
named_context_url(@context, :context_discussion_topics_url))

View File

@ -321,6 +321,8 @@ class ExternalToolsController < ApplicationController
selection_type = params[:launch_type] || "#{@context.class.base_class.to_s.downcase}_navigation"
if find_tool(params[:id], selection_type)
log_asset_access(@tool, "external_tools", "external_tools")
@return_url = external_content_success_url('external_tool_redirect')
@redirect_return = true

View File

@ -25,6 +25,8 @@ class OutcomesController < ApplicationController
def index
if authorized_action(@context, @current_user, :read)
return unless tab_enabled?(@context.class::TAB_OUTCOMES)
log_asset_access("outcomes:#{@context.asset_string}", "outcomes", "other")
@root_outcome_group = @context.root_outcome_group
if common_core_group_id = Setting.get(AcademicBenchmark.common_core_setting_key, nil)
common_core_group_id = common_core_group_id.to_i
@ -53,6 +55,8 @@ class OutcomesController < ApplicationController
@outcome = @context.linked_learning_outcomes.find(params[:id])
if authorized_action(@context, @current_user, :manage_outcomes)
log_asset_access(@outcome, "outcomes", "outcomes")
codes = [@context].map(&:asset_string)
if @context.is_a?(Account)
if @context == @outcome.context

View File

@ -176,6 +176,7 @@ class WikiPagesController < ApplicationController
end
if authorized_action(@context.wiki, @current_user, :read)
log_asset_access("pages:#{@context.asset_string}", "pages", "other")
js_env :wiki_page_menu_tools => external_tools_display_hashes(:wiki_page_menu)
@padless = true
end

View File

@ -128,6 +128,8 @@ class AssetUserAccess < ActiveRecord::Base
asset.title
elsif self.asset.is_a? Enrollment
asset.user.name
elsif self.asset.respond_to?(:name) && !self.asset.name.nil?
asset.name
else
self.asset_code
end
@ -142,7 +144,8 @@ class AssetUserAccess < ActiveRecord::Base
split = self.asset_code.split(/\:/)
if split[1] == self.context_code
# TODO: i18n
"#{self.context_type} #{split[0].titleize}"
title = split[0] == "topics" ? "Discussions" : split[0].titleize
"#{self.context_type} #{title}"
else
self.display_name
end
@ -159,7 +162,9 @@ class AssetUserAccess < ActiveRecord::Base
end
def asset_class_name
self.asset.class.name.underscore if self.asset
name = self.asset.class.name.underscore if self.asset
name = "Quiz" if name == "Quizzes::Quiz"
name
end
def log( kontext, accessed )

View File

@ -38,6 +38,7 @@ module Context
CalendarEvent = ::CalendarEvent
Collaboration = ::Collaboration
ContentTag = ::ContentTag
ContextExternalTool = ::ContextExternalTool
ContextModule = ::ContextModule
DiscussionEntry = ::DiscussionEntry
DiscussionTopic = ::DiscussionTopic
@ -213,6 +214,8 @@ module Context
res = nil
if klass == WikiPage
res = context.wiki.wiki_pages.where(id: id).first
elsif klass == ContextExternalTool
res = klass.find_external_tool_by_id(id, context)
elsif (klass.column_names & ['context_id', 'context_type']).length == 2
res = klass.where(context_id: context, context_type: context.class.to_s, id: id).first
elsif klass == Attachment

View File

@ -467,6 +467,10 @@ class ContextExternalTool < ActiveRecord::Base
scope.order(ContextExternalTool.best_unicode_collation_key('name'))
end
def self.find_external_tool_by_id(id, context)
self.where(:id => id).polymorphic_where(:context => contexts_to_search(context)).first
end
# Order of precedence: Basic LTI defines precedence as first
# checking for a match on domain. Subdomains count as a match
# on less-specific domains, but the most-specific domain will