90 lines
3.2 KiB
Ruby
90 lines
3.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
#
|
|
# Copyright (C) 2020 - 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/>.
|
|
|
|
module GoogleAnalyticsDimensions
|
|
# Prepare some contextual data to supplement a pageview hit when submitting to
|
|
# GA to provide the analyst with more context surrounding the request:
|
|
#
|
|
# {
|
|
# "enrollments": BoolMask.<student, teacher, observer>,
|
|
# "admin": BoolMask.<admin, site_admin>,
|
|
# "masquerading": Bool
|
|
# }
|
|
#
|
|
# Bool is a "0" or "1" value (encoded as strings) while "BoolMask" is a stream
|
|
# of bools encoded also as a string. For example:
|
|
#
|
|
# {
|
|
# "enrollments": "010", # a teacher
|
|
# "admin": "11", # an admin and a site admin
|
|
# "masquerading": "0" # nope
|
|
# }
|
|
#
|
|
# Encoding flags in such a way gives us the flexibility to represent future
|
|
# values while also giving the analyst more freedom in reporting (GA supports
|
|
# regex filtering.)
|
|
def self.calculate(domain_root_account:, user:, real_user:)
|
|
user_roles = user ? user.roles(domain_root_account) : []
|
|
|
|
{
|
|
admin: _encode_admin_status(roles: user_roles),
|
|
enrollments: _encode_enrollments(roles: user_roles),
|
|
masquerading: _encode_masquerading_status(user: user, real_user: real_user),
|
|
org_type: _encode_org_type(account: domain_root_account),
|
|
user_id: _compute_non_compromising_user_id(user: user),
|
|
}
|
|
end
|
|
|
|
# we only need some identifier that GA can utilize to track users across
|
|
# different devices but we don't want it to know who the users are (e.g. their
|
|
# canvas id)
|
|
#
|
|
# see https://support.google.com/analytics/answer/2992042?hl=en
|
|
# see https://developers.google.com/analytics/devguides/collection/analyticsjs/cookies-user-id
|
|
def self._compute_non_compromising_user_id(user:)
|
|
user ? Canvas::Security.hmac_sha512(user.id.to_s)[0,32] : nil
|
|
end
|
|
|
|
def self._encode_admin_status(roles:)
|
|
# again, look at User#user_roles for the definition
|
|
%w[ admin root_admin ].map do |enrollment_type|
|
|
roles.include?(enrollment_type) ? '1' : '0'
|
|
end.join('')
|
|
|
|
end
|
|
|
|
def self._encode_enrollments(roles:)
|
|
# keep in mind that some of these roles may be rolled up from different
|
|
# enrollment types, see User#user_roles for the meat
|
|
%w[ student teacher observer ].map do |enrollment_type|
|
|
roles.include?(enrollment_type) ? '1' : '0'
|
|
end.join('')
|
|
end
|
|
|
|
def self._encode_org_type(account:)
|
|
account&.external_integration_keys&.find_by(
|
|
key_type: 'salesforce_org_type'
|
|
)&.key_value
|
|
end
|
|
|
|
def self._encode_masquerading_status(user:, real_user:)
|
|
real_user && real_user != user ? '1' : '0'
|
|
end
|
|
end
|