log the remote_ip in page views
refs CNVS-8392 also update the page view API documentation test plan: * with this commit applied, page views will now log the remote ip of requests, and return that ip in the api and csv downloads * regenerate api docs with rake doc:api, and verify that the user section now has expanded information on the api response Change-Id: If463e211515881db6ce1f75c9bbca8c7fbcf7589 Reviewed-on: https://gerrit.instructure.com/24880 Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Cody Cutrer <cody@instructure.com> QA-Review: Jeremy Putnam <jeremyp@instructure.com> QA-Review: August Thornton <august@instructure.com> Product-Review: Brian Palmer <brianp@instructure.com>
This commit is contained in:
parent
588b3f02d2
commit
e1b650f53f
|
@ -17,6 +17,123 @@
|
|||
#
|
||||
|
||||
# @API Users
|
||||
#
|
||||
# @model PageView
|
||||
# {
|
||||
# "id": "PageView",
|
||||
# "description": "The record of a user page view access in Canvas",
|
||||
# "required": ["request_id"],
|
||||
# "properties": {
|
||||
# "request_id": {
|
||||
# "description": "A UUID representing the page view",
|
||||
# "example": "3e246700-e305-0130-51de-02e33aa501ef",
|
||||
# "type": "string",
|
||||
# "format": "uuid"
|
||||
# },
|
||||
# "user_id": {
|
||||
# "description": "The ID of the user for this page view",
|
||||
# "example": "1234",
|
||||
# "type": "integer",
|
||||
# "format": "int64"
|
||||
# },
|
||||
# "url": {
|
||||
# "description": "The URL requested",
|
||||
# "example": "https://canvas.instructure.com/conversations",
|
||||
# "type": "string"
|
||||
# },
|
||||
# "context_type": {
|
||||
# "description": "The type of context for the request",
|
||||
# "example": "Course",
|
||||
# "type": "string"
|
||||
# },
|
||||
# "context_id": {
|
||||
# "description": "The ID of the context for the request (course id if context_type is Course, etc)",
|
||||
# "example": "1234",
|
||||
# "type": "integer",
|
||||
# "format": "int64"
|
||||
# },
|
||||
# "asset_type": {
|
||||
# "description": "The type of asset in the context for the request, if any",
|
||||
# "example": "Discussion",
|
||||
# "type": "string"
|
||||
# },
|
||||
# "asset_id": {
|
||||
# "description": "The ID of the asset for the request, if any",
|
||||
# "example": "1234",
|
||||
# "type": "integer",
|
||||
# "format": "int64"
|
||||
# },
|
||||
# "controller": {
|
||||
# "description": "The rails controller that handled the request",
|
||||
# "example": "discussions",
|
||||
# "type": "string"
|
||||
# },
|
||||
# "action": {
|
||||
# "description": "The rails action that handled the request",
|
||||
# "example": "index",
|
||||
# "type": "string"
|
||||
# },
|
||||
# "contributed": {
|
||||
# "description": "True if the request counted as contributing, such as editing a wiki page",
|
||||
# "example": "false",
|
||||
# "type": "boolean"
|
||||
# },
|
||||
# "interaction_seconds": {
|
||||
# "description": "An approximation of how long the user spent on the page, in seconds",
|
||||
# "example": "7.21",
|
||||
# "type": "float"
|
||||
# },
|
||||
# "created_at": {
|
||||
# "description": "When the request was made",
|
||||
# "example": "2013-10-01T19:49:47Z",
|
||||
# "type": "datetime",
|
||||
# "format": "iso8601"
|
||||
# },
|
||||
# "user_request": {
|
||||
# "description": "A flag indicating whether the request was user-initiated, or automatic (such as an AJAX call)",
|
||||
# "example": "true",
|
||||
# "type": "boolean"
|
||||
# },
|
||||
# "render_time": {
|
||||
# "description": "How long the response took to render, in seconds",
|
||||
# "example": "0.369",
|
||||
# "type": "float"
|
||||
# },
|
||||
# "user_agent": {
|
||||
# "description": "The user-agent of the browser or program that made the request",
|
||||
# "example": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/536.30.1 (KHTML, like Gecko) Version/6.0.5 Safari/536.30.1",
|
||||
# "type": "string"
|
||||
# },
|
||||
# "participated": {
|
||||
# "description": "True if the request counted as participating, such as submitting homework",
|
||||
# "example": "false",
|
||||
# "type": "boolean"
|
||||
# },
|
||||
# "account_id": {
|
||||
# "description": "The ID of the account context for this page view",
|
||||
# "example": "1234",
|
||||
# "type": "integer",
|
||||
# "format": "int64"
|
||||
# },
|
||||
# "real_user_id": {
|
||||
# "description": "The ID of the actual user who made this request, if the request was made by a user who was masquerading",
|
||||
# "example": "1234",
|
||||
# "type": "integer",
|
||||
# "format": "int64"
|
||||
# },
|
||||
# "http_method": {
|
||||
# "description": "The HTTP method such as GET or POST",
|
||||
# "example": "GET",
|
||||
# "type": "string"
|
||||
# },
|
||||
# "remote_ip": {
|
||||
# "description": "The origin IP address of the request",
|
||||
# "example": "173.194.46.71",
|
||||
# "type": "string"
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
|
||||
class PageViewsController < ApplicationController
|
||||
before_filter :require_user, :only => [:index]
|
||||
|
||||
|
@ -38,12 +155,7 @@ class PageViewsController < ApplicationController
|
|||
# @argument end_time [Optional, DateTime]
|
||||
# The end of the time range from which you want page views.
|
||||
#
|
||||
# @response_field interaction_seconds The number of seconds the user actively interacted with the page. This is a best guess, using heuristics such as browser input events.
|
||||
# @response_field url The full canvas URL of the page view.
|
||||
# @response_field user_agent The browser identifier or other user agent that was used to make the request.
|
||||
# @response_field controller The Rails controller that processed the request.
|
||||
# @response_field action The action in the Rails controller that processed the request.
|
||||
# @response_field context_type The type of "context" of the request, e.g. Account or Course.
|
||||
# @returns [PageView]
|
||||
def index
|
||||
@user = api_find(User, params[:user_id])
|
||||
if authorized_action(@user, @current_user, :view_statistics)
|
||||
|
|
|
@ -45,6 +45,7 @@ class PageView < ActiveRecord::Base
|
|||
self.new(attributes).tap do |p|
|
||||
p.url = LoggingFilter.filter_uri(request.url)[0,255]
|
||||
p.http_method = request.method.to_s
|
||||
p.remote_ip = request.remote_ip
|
||||
p.controller = request.path_parameters['controller']
|
||||
p.action = request.path_parameters['action']
|
||||
p.session_id = request.session_options[:id].to_s.force_encoding(Encoding::UTF_8).presence
|
||||
|
@ -79,7 +80,7 @@ class PageView < ActiveRecord::Base
|
|||
end
|
||||
|
||||
# the list of columns we display to users, export to csv, etc
|
||||
EXPORTED_COLUMNS = %w(request_id user_id url context_id context_type asset_id asset_type controller action contributed interaction_seconds created_at user_request render_time user_agent participated account_id real_user_id http_method)
|
||||
EXPORTED_COLUMNS = %w(request_id user_id url context_id context_type asset_id asset_type controller action contributed interaction_seconds created_at user_request render_time user_agent participated account_id real_user_id http_method remote_ip)
|
||||
|
||||
def self.page_views_enabled?
|
||||
!!page_view_method
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
class AddCassandraPageViewsRemoteIp < ActiveRecord::Migration
|
||||
tag :predeploy
|
||||
|
||||
include Canvas::Cassandra::Migration
|
||||
|
||||
def self.cassandra_cluster
|
||||
'page_views'
|
||||
end
|
||||
|
||||
def self.up
|
||||
cassandra.execute %{ ALTER TABLE page_views ADD remote_ip text; }
|
||||
end
|
||||
|
||||
def self.down
|
||||
cassandra.execute %{ ALTER TABLE page_views DROP remote_ip; }
|
||||
end
|
||||
end
|
|
@ -0,0 +1,11 @@
|
|||
class AddPageViewsRemoteIp < ActiveRecord::Migration
|
||||
tag :predeploy
|
||||
|
||||
def self.up
|
||||
add_column :page_views, :remote_ip, :string
|
||||
end
|
||||
|
||||
def self.down
|
||||
remove_column :page_views, :remote_ip
|
||||
end
|
||||
end
|
|
@ -340,7 +340,7 @@ describe PageView do
|
|||
describe '.generate' do
|
||||
let(:params) { {'action' => 'path', 'controller' => 'some'} }
|
||||
let(:session) { {:id => '42'} }
|
||||
let(:request) { stub(:url => (@url || 'host.com/some/path'), :path_parameters => params, :user_agent => 'Mozilla', :session_options => session, :method => :get) }
|
||||
let(:request) { stub(:url => (@url || 'host.com/some/path'), :path_parameters => params, :user_agent => 'Mozilla', :session_options => session, :method => :get, :remote_ip => '0.0.0.0') }
|
||||
let(:user) { User.new }
|
||||
let(:attributes) { {:real_user => user, :user => user } }
|
||||
|
||||
|
@ -360,6 +360,7 @@ describe PageView do
|
|||
its(:created_at) { should_not be_nil }
|
||||
its(:updated_at) { should_not be_nil }
|
||||
its(:http_method) { should == 'get' }
|
||||
its(:remote_ip) { should == '0.0.0.0' }
|
||||
|
||||
it "should filter sensitive url params" do
|
||||
@url = 'http://canvas.example.com/api/v1/courses/1?access_token=SUPERSECRET'
|
||||
|
|
Loading…
Reference in New Issue