canvas-lms/lib/services/rich_content.rb

78 lines
2.7 KiB
Ruby
Raw Normal View History

#
# Copyright (C) 2015 - 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 Services
class RichContent
def self.env_for(root_account, risk_level: :highrisk, user: nil, domain: nil, real_user: nil, context: nil)
clean up RCE abstraction layer and service sidebar refs CNVS-26704, CNVS-26707 RichContentEditor and RceCommandShim: * move risk level management all to the server side; just one flag in JS is set contextually in the server response based on server chosen risk level for the page * flatten the RichContentEditor and RceCommandShim modules to singleton method collections, rather than instances * add RceCommandShim.focus and .destroy methods that more gracefully divide the implementations vs. just using send(target, 'focus') or send(target, 'destroy') Editor Loading and Focus * replace attachSidebarTo calls -- which always (see one exception below) paired with a loadNewEditor call -- are replaced with the focus:true option to loadNewEditor. when on, the editor is explicitly focused after load; it no longer turns on tinymce auto_focus * on internal tinymce events that trigger 'editor_box_focus' events, explicitly focus the editor. this was an attachSidebarTo call (the exception) only registered for quizzes, but now more generally. Editor Destruction * replace callOnRCE(target, 'destroy') and target._removeEditor() calls with new RichContentEditor.destroyRCE(target). destroys the editor as before, but does so through new RceCommandShim.destroy and also hides sidebar (so no need for explicit hideSidebar calls, which only ever accompanied editor destruction) Sidebar * add remoteSidebar.show() and remoteSidebar.hide() polyfills * separate sidebar abstraction into Sidebar module. public interface is still through RichContentEditor: initSidebar calls Sidebar.init and show/hide are only called from RichContentEditor implementation in response to editor focus and destruction. * allow registering callbacks during initSidebar for when the sidebar is shown/hidden. so the desired action doesn't have to be coupled with individual calls to loadNewEditor and destroyRCE. * ensure initSidebar, when present, precedes loadNewEditor. so if there's going to be a sidebar, it's initialized before the editor load tries to show it. * add initSidebar calls to discussions/Reply.coffee and editor/EditorToggle.coffee so that they get automatic focus, sidebar show on editor load, and sidebar hide on editor destruction, previously provided by util/wikiSidebarWithMultipleEditors.coffee. * cache wikiSidebar elements as soon as initSidebar is called, rather than waiting for domready, so that initSidebar doesn't have to be in a domready itself. Miscellaneous * replace calls of target._justGetCode() and target._setContentCode(...) with RichContentEditor.callOnRCE(target, 'get_code') and RichContentEditor.callonRCE(target, 'set_code', ...), respectively * remove a dead legacy bundle and d dead module only used by that dead bundle * clean up dependencies to remove unnecessary references to wikiSidebar, compiled/tinymce, and tinymce.editor_box outside of the abstraction layer or legacy-only code. * fix idGenerator fragile spec bug test-plan: there should not be significant changes in _what_ the RCE or sidebar does. but significant changes in _how_. so no new features to test, but a thorough regression on RCE and sidebar behaviors is probably in order (sorry) Change-Id: I4e0cbcb3dcb28152750bf9267d795a179822a601 Reviewed-on: https://gerrit.instructure.com/75469 Tested-by: Jenkins Reviewed-by: Ethan Vizitei <evizitei@instructure.com> QA-Review: Jeremy Putnam <jeremyp@instructure.com> Product-Review: Ethan Vizitei <evizitei@instructure.com>
2016-03-19 04:21:07 +08:00
enabled = contextually_on(root_account, risk_level)
env_hash = { RICH_CONTENT_SERVICE_ENABLED: enabled }
if enabled
env_hash = env_hash.merge(service_settings)
if user && domain
add workflow and additional state to jwt for rcs for a given workflow, services consuming canvas jwts may need access to additional state (feature flags, permissions, etc). this commit introduces the ability to to define state requirements for a jwt based on its workflows, context and user. the concept of jwt workflow has been made plural and it expects it to be an array of workflows. a token for one service may need to be used in multiple workflows (i.e. a quiz token may need to work as a rich content token as well). this commit defines the :rich_content workflow which includes upload and usage rights information. tokens also include context type and id. since the workflow state may be specific to the context, this provides a way for the service to validate that the token is being used in the correct context. code that generates conditional-release tokens has been updated to use the workflows array. this won't break anything becuase, even though it is including in the token, it is not being validated yet. future validations will check for inclusion in the array. refs CNVS-30966, refs CNVS-32094 test plan: - launch a page with the rich content service side bar - ensure the request to the proxy don't return 401 status codes - a test plan for the consuption of the new data in the token will come with a seperate RCS commit Change-Id: I9e643995cb98547664f721a9b5d8c9441010eea9 Reviewed-on: https://gerrit.instructure.com/89012 Reviewed-by: Simon Williams <simon@instructure.com> Tested-by: Jenkins QA-Review: Jeremy Putnam <jeremyp@instructure.com> Product-Review: Brent Burgoyne <bburgoyne@instructure.com>
2016-08-30 01:19:45 +08:00
env_hash[:JWT] = Canvas::Security::ServicesJwt.for_user(
domain,
user,
context: context,
real_user: real_user,
workflows: [:rich_content, :ui]
add workflow and additional state to jwt for rcs for a given workflow, services consuming canvas jwts may need access to additional state (feature flags, permissions, etc). this commit introduces the ability to to define state requirements for a jwt based on its workflows, context and user. the concept of jwt workflow has been made plural and it expects it to be an array of workflows. a token for one service may need to be used in multiple workflows (i.e. a quiz token may need to work as a rich content token as well). this commit defines the :rich_content workflow which includes upload and usage rights information. tokens also include context type and id. since the workflow state may be specific to the context, this provides a way for the service to validate that the token is being used in the correct context. code that generates conditional-release tokens has been updated to use the workflows array. this won't break anything becuase, even though it is including in the token, it is not being validated yet. future validations will check for inclusion in the array. refs CNVS-30966, refs CNVS-32094 test plan: - launch a page with the rich content service side bar - ensure the request to the proxy don't return 401 status codes - a test plan for the consuption of the new data in the token will come with a seperate RCS commit Change-Id: I9e643995cb98547664f721a9b5d8c9441010eea9 Reviewed-on: https://gerrit.instructure.com/89012 Reviewed-by: Simon Williams <simon@instructure.com> Tested-by: Jenkins QA-Review: Jeremy Putnam <jeremyp@instructure.com> Product-Review: Brent Burgoyne <bburgoyne@instructure.com>
2016-08-30 01:19:45 +08:00
)
end
add workflow and additional state to jwt for rcs for a given workflow, services consuming canvas jwts may need access to additional state (feature flags, permissions, etc). this commit introduces the ability to to define state requirements for a jwt based on its workflows, context and user. the concept of jwt workflow has been made plural and it expects it to be an array of workflows. a token for one service may need to be used in multiple workflows (i.e. a quiz token may need to work as a rich content token as well). this commit defines the :rich_content workflow which includes upload and usage rights information. tokens also include context type and id. since the workflow state may be specific to the context, this provides a way for the service to validate that the token is being used in the correct context. code that generates conditional-release tokens has been updated to use the workflows array. this won't break anything becuase, even though it is including in the token, it is not being validated yet. future validations will check for inclusion in the array. refs CNVS-30966, refs CNVS-32094 test plan: - launch a page with the rich content service side bar - ensure the request to the proxy don't return 401 status codes - a test plan for the consuption of the new data in the token will come with a seperate RCS commit Change-Id: I9e643995cb98547664f721a9b5d8c9441010eea9 Reviewed-on: https://gerrit.instructure.com/89012 Reviewed-by: Simon Williams <simon@instructure.com> Tested-by: Jenkins QA-Review: Jeremy Putnam <jeremyp@instructure.com> Product-Review: Brent Burgoyne <bburgoyne@instructure.com>
2016-08-30 01:19:45 +08:00
# TODO: Remove once rich content service pull from jwt
env_hash[:RICH_CONTENT_CAN_UPLOAD_FILES] = (
user &&
context &&
context.grants_any_right?(user, :manage_files)
) || false
end
env_hash
end
class << self
private
def check_feature_flag(root_account, flag)
return false unless root_account.present?
root_account.feature_enabled?(flag) || false # ensure true boolean
end
def service_settings
settings = Canvas::DynamicSettings.from_cache("rich-content-service", expires_in: 5.minutes, use_env: false)
{
RICH_CONTENT_APP_HOST: settings["app-host"],
RICH_CONTENT_CDN_HOST: settings["cdn-host"]
}
rescue Imperium::TimeoutError,
Imperium::UnableToConnectError,
Canvas::DynamicSettings::ConsulError => e
Canvas::Errors.capture_exception(:rce_flag, e)
{
RICH_CONTENT_APP_HOST: "error",
RICH_CONTENT_CDN_HOST: "error"
}
end
clean up RCE abstraction layer and service sidebar refs CNVS-26704, CNVS-26707 RichContentEditor and RceCommandShim: * move risk level management all to the server side; just one flag in JS is set contextually in the server response based on server chosen risk level for the page * flatten the RichContentEditor and RceCommandShim modules to singleton method collections, rather than instances * add RceCommandShim.focus and .destroy methods that more gracefully divide the implementations vs. just using send(target, 'focus') or send(target, 'destroy') Editor Loading and Focus * replace attachSidebarTo calls -- which always (see one exception below) paired with a loadNewEditor call -- are replaced with the focus:true option to loadNewEditor. when on, the editor is explicitly focused after load; it no longer turns on tinymce auto_focus * on internal tinymce events that trigger 'editor_box_focus' events, explicitly focus the editor. this was an attachSidebarTo call (the exception) only registered for quizzes, but now more generally. Editor Destruction * replace callOnRCE(target, 'destroy') and target._removeEditor() calls with new RichContentEditor.destroyRCE(target). destroys the editor as before, but does so through new RceCommandShim.destroy and also hides sidebar (so no need for explicit hideSidebar calls, which only ever accompanied editor destruction) Sidebar * add remoteSidebar.show() and remoteSidebar.hide() polyfills * separate sidebar abstraction into Sidebar module. public interface is still through RichContentEditor: initSidebar calls Sidebar.init and show/hide are only called from RichContentEditor implementation in response to editor focus and destruction. * allow registering callbacks during initSidebar for when the sidebar is shown/hidden. so the desired action doesn't have to be coupled with individual calls to loadNewEditor and destroyRCE. * ensure initSidebar, when present, precedes loadNewEditor. so if there's going to be a sidebar, it's initialized before the editor load tries to show it. * add initSidebar calls to discussions/Reply.coffee and editor/EditorToggle.coffee so that they get automatic focus, sidebar show on editor load, and sidebar hide on editor destruction, previously provided by util/wikiSidebarWithMultipleEditors.coffee. * cache wikiSidebar elements as soon as initSidebar is called, rather than waiting for domready, so that initSidebar doesn't have to be in a domready itself. Miscellaneous * replace calls of target._justGetCode() and target._setContentCode(...) with RichContentEditor.callOnRCE(target, 'get_code') and RichContentEditor.callonRCE(target, 'set_code', ...), respectively * remove a dead legacy bundle and d dead module only used by that dead bundle * clean up dependencies to remove unnecessary references to wikiSidebar, compiled/tinymce, and tinymce.editor_box outside of the abstraction layer or legacy-only code. * fix idGenerator fragile spec bug test-plan: there should not be significant changes in _what_ the RCE or sidebar does. but significant changes in _how_. so no new features to test, but a thorough regression on RCE and sidebar behaviors is probably in order (sorry) Change-Id: I4e0cbcb3dcb28152750bf9267d795a179822a601 Reviewed-on: https://gerrit.instructure.com/75469 Tested-by: Jenkins Reviewed-by: Ethan Vizitei <evizitei@instructure.com> QA-Review: Jeremy Putnam <jeremyp@instructure.com> Product-Review: Ethan Vizitei <evizitei@instructure.com>
2016-03-19 04:21:07 +08:00
def contextually_on(root_account, risk_level)
check_feature_flag(root_account, :rich_content_service) && (
risk_level == :basic ||
(risk_level == :sidebar && check_feature_flag(root_account, :rich_content_service_with_sidebar)) ||
check_feature_flag(root_account, :rich_content_service_high_risk)
)
end
end
end
end