2013-04-20 03:55:00 +08:00
|
|
|
#
|
|
|
|
# Copyright (C) 2011 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 Pages
|
|
|
|
#
|
|
|
|
# Pages are rich content associated with Courses and Groups in Canvas.
|
|
|
|
# The Pages API allows you to create, retrieve, update, and delete ages.
|
|
|
|
#
|
|
|
|
# @object Page
|
|
|
|
# {
|
|
|
|
# // the unique locator for the page
|
|
|
|
# url: "my-page-title",
|
|
|
|
#
|
|
|
|
# // the title of the page
|
|
|
|
# title: "My Page Title",
|
|
|
|
#
|
|
|
|
# // the creation date for the page
|
|
|
|
# created_at: "2012-08-06T16:46:33-06:00",
|
|
|
|
#
|
|
|
|
# // the date the page was last updated
|
|
|
|
# updated_at: "2012-08-08T14:25:20-06:00",
|
|
|
|
#
|
|
|
|
# // whether this page is hidden from students
|
|
|
|
# // (note: students will never see this true; pages hidden from them will be omitted from results)
|
|
|
|
# hide_from_students: false,
|
|
|
|
#
|
|
|
|
# // roles allowed to edit the page; comma-separated list comprising a combination of
|
|
|
|
# // 'teachers', 'students', and/or 'public'
|
|
|
|
# // if not supplied, course defaults are used
|
|
|
|
# editing_roles: "teachers,students",
|
|
|
|
#
|
|
|
|
# // the User who last edited the page
|
|
|
|
# // (this may not be present if the page was imported from another system)
|
|
|
|
# last_edited_by: {
|
|
|
|
# id: 133,
|
|
|
|
# display_name: "Rey del Pueblo",
|
|
|
|
# avatar_image_url: "https://canvas.example.com/images/thumbnails/bm90aGluZyBoZXJl",
|
|
|
|
# html_url: "https://canvas.example.com/courses/789/users/133"
|
|
|
|
# },
|
|
|
|
#
|
|
|
|
# // the page content, in HTML
|
|
|
|
# // (present when requesting a single page; omitted when listing pages)
|
|
|
|
# body: "<p>Page Content</p>",
|
|
|
|
#
|
|
|
|
# // whether the page is published
|
2013-05-17 05:02:04 +08:00
|
|
|
# published: true,
|
|
|
|
#
|
|
|
|
# // whether this page is the front page for the wiki
|
2013-06-05 07:51:27 +08:00
|
|
|
# front_page: false,
|
|
|
|
#
|
|
|
|
# // Whether or not this is locked for the user.
|
|
|
|
# locked_for_user: false,
|
|
|
|
#
|
|
|
|
# // (Optional) Information for the user about the lock. Present when locked_for_user is true.
|
|
|
|
# lock_info: {
|
|
|
|
# // Asset string for the object causing the lock
|
|
|
|
# asset_string: "wiki_page_1",
|
|
|
|
#
|
|
|
|
# // (Optional) Context module causing the lock.
|
|
|
|
# context_module: { ... }
|
|
|
|
# },
|
|
|
|
#
|
|
|
|
# // (Optional) An explanation of why this is locked for the user. Present when locked_for_user is true.
|
|
|
|
# lock_explanation: "This discussion is locked until September 1 at 12:00am"
|
2013-04-20 03:55:00 +08:00
|
|
|
# }
|
|
|
|
class WikiPagesApiController < ApplicationController
|
|
|
|
before_filter :require_context
|
|
|
|
before_filter :get_wiki_page, :except => [:create, :index]
|
|
|
|
|
|
|
|
include Api::V1::WikiPage
|
|
|
|
|
|
|
|
# @API List pages
|
|
|
|
#
|
|
|
|
# List the wiki pages associated with a course or group
|
|
|
|
#
|
|
|
|
# @argument sort [optional] Sort results by this field: one of 'title', 'created_at', or 'updated_at'
|
|
|
|
# @argument order [optional] The sorting order: 'asc' (default) or 'desc'
|
2013-07-09 03:06:34 +08:00
|
|
|
# @argument search_term (optional) The partial title of the pages to match and return.
|
2013-04-20 03:55:00 +08:00
|
|
|
#
|
|
|
|
# @example_request
|
|
|
|
# curl -H 'Authorization: Bearer <token>' \
|
|
|
|
# https://<canvas>/api/v1/courses/123/pages?sort=title&order=asc
|
|
|
|
#
|
|
|
|
# @returns [Page]
|
|
|
|
def index
|
|
|
|
if authorized_action(@context.wiki, @current_user, :read)
|
|
|
|
pages_route = polymorphic_url([:api_v1, @context, :wiki_pages])
|
|
|
|
# omit body from selection, since it's not included in index results
|
2013-06-05 07:51:27 +08:00
|
|
|
scope = @context.wiki.wiki_pages.select(WikiPage.column_names - ['body']).includes(:user)
|
2013-04-20 03:55:00 +08:00
|
|
|
scope = @context.grants_right?(@current_user, session, :view_unpublished_items) ? scope.not_deleted : scope.active
|
|
|
|
scope = scope.visible_to_students unless @context.grants_right?(@current_user, session, :view_hidden_items)
|
|
|
|
|
2013-07-09 03:06:34 +08:00
|
|
|
scope = scope.title_like(params[:search_term]) if params[:search_term]
|
|
|
|
|
2013-04-20 03:55:00 +08:00
|
|
|
order_clause = case params[:sort]
|
|
|
|
when 'title'
|
|
|
|
WikiPage.title_order_by_clause
|
|
|
|
when 'created_at'
|
|
|
|
'wiki_pages.created_at'
|
|
|
|
when 'updated_at'
|
|
|
|
'wiki_pages.updated_at'
|
|
|
|
else
|
|
|
|
'wiki_pages.id'
|
|
|
|
end
|
|
|
|
order_clause += ' DESC' if params[:order] == 'desc'
|
|
|
|
scope = scope.order(order_clause)
|
|
|
|
|
|
|
|
wiki_pages = Api.paginate(scope, self, pages_route)
|
|
|
|
render :json => wiki_pages_json(wiki_pages, @current_user, session)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# @API Show page
|
|
|
|
#
|
|
|
|
# Retrieve the content of a wiki page
|
|
|
|
#
|
2013-05-17 05:02:04 +08:00
|
|
|
# @argument url the unique identifier for a page.
|
2013-04-20 03:55:00 +08:00
|
|
|
#
|
|
|
|
# @example_request
|
|
|
|
# curl -H 'Authorization: Bearer <token>' \
|
2013-05-17 05:02:04 +08:00
|
|
|
# https://<canvas>/api/v1/courses/123/pages/my-page-url
|
|
|
|
#
|
|
|
|
# @example_request
|
|
|
|
# curl -H 'Authorization: Bearer <token>' \
|
|
|
|
# https://<canvas>/api/v1/courses/123/front_page
|
2013-04-20 03:55:00 +08:00
|
|
|
#
|
|
|
|
# @returns Page
|
|
|
|
def show
|
|
|
|
if authorized_action(@page, @current_user, :read)
|
|
|
|
@page.increment_view_count(@current_user, @context)
|
|
|
|
log_asset_access(@page, "wiki", @wiki)
|
|
|
|
render :json => wiki_page_json(@page, @current_user, session)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# @API Create page
|
|
|
|
#
|
|
|
|
# Create a new wiki page
|
|
|
|
#
|
|
|
|
# @argument wiki_page[title] the title for the new page.
|
|
|
|
# @argument wiki_page[body] the content for the new page.
|
|
|
|
# @argument wiki_page[hide_from_students] [boolean] whether the page should be hidden from students.
|
|
|
|
# @argument wiki_page[notify_of_update] [boolean] whether participants should be notified when this page changes.
|
|
|
|
# @argument wiki_page[published] [optional] [boolean] whether the page is published (true) or draft state (false).
|
2013-05-17 05:02:04 +08:00
|
|
|
# @argument wiki_page[front_page] [optional] [boolean] set an unhidden page as the front page (if true)
|
2013-04-20 03:55:00 +08:00
|
|
|
#
|
|
|
|
# @example_request
|
|
|
|
# curl -X POST -H 'Authorization: Bearer <token>' \
|
|
|
|
# https://<canvas>/api/v1/courses/123/pages?wiki_page[title]=New+page&wiki_page[body]=New+body+text
|
|
|
|
#
|
|
|
|
# @returns Page
|
|
|
|
def create
|
|
|
|
@page = @context.wiki.wiki_pages.build
|
|
|
|
if authorized_action(@page, @current_user, :update)
|
2013-05-17 05:02:04 +08:00
|
|
|
get_front_page_params
|
2013-04-20 03:55:00 +08:00
|
|
|
attrs_to_update = process_update_params
|
2013-05-17 05:02:04 +08:00
|
|
|
if @page.update_attributes(attrs_to_update) && process_front_page
|
2013-04-20 03:55:00 +08:00
|
|
|
log_asset_access(@page, "wiki", @wiki, 'participate')
|
|
|
|
render :json => wiki_page_json(@page, @current_user, session)
|
|
|
|
else
|
|
|
|
render :json => @page.errors.to_json, :status => :bad_request
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# @API Update page
|
|
|
|
#
|
|
|
|
# Update the title or contents of a wiki page
|
|
|
|
#
|
|
|
|
# @argument url the unique identifier for a page.
|
|
|
|
# @argument wiki_page[title] [optional] the new title for the page.
|
|
|
|
# NOTE: changing a page's title will change its url. The updated url will be returned in the result.
|
|
|
|
# @argument wiki_page[body] [optional] the new content for the page.
|
|
|
|
# @argument wiki_page[hide_from_students] [optional] boolean; whether the page should be hidden from students.
|
|
|
|
# @argument wiki_page[notify_of_update] [optional] [boolean] notify participants that the wiki page has been changed.
|
|
|
|
# @argument wiki_page[published] [optional] [boolean] whether the page is published (true) or draft state (false)
|
2013-05-17 05:02:04 +08:00
|
|
|
# @argument wiki_page[front_page] [optional] [boolean] set an unhidden page as the front page (if true), or un-set it (if false)
|
2013-04-20 03:55:00 +08:00
|
|
|
#
|
|
|
|
# @example_request
|
|
|
|
# curl -X PUT -H 'Authorization: Bearer <token>' \
|
|
|
|
# https://<canvas>/api/v1/courses/123/pages/the-page-url?wiki_page[body]=Updated+body+text
|
|
|
|
#
|
2013-05-17 05:02:04 +08:00
|
|
|
# @example_request
|
|
|
|
# curl -X PUT -H 'Authorization: Bearer <token>' \
|
|
|
|
# https://<canvas>/api/v1/courses/123/front_page?wiki_page[body]=Updated+body+text
|
|
|
|
#
|
2013-04-20 03:55:00 +08:00
|
|
|
# @returns Page
|
|
|
|
def update
|
|
|
|
if authorized_action(@page, @current_user, :update_content)
|
2013-05-17 05:02:04 +08:00
|
|
|
get_front_page_params
|
2013-04-20 03:55:00 +08:00
|
|
|
attrs_to_update = process_update_params
|
2013-05-17 05:02:04 +08:00
|
|
|
|
|
|
|
if @page.update_attributes(attrs_to_update) && process_front_page
|
2013-04-20 03:55:00 +08:00
|
|
|
log_asset_access(@page, "wiki", @wiki, 'participate')
|
|
|
|
@page.context_module_action(@current_user, @context, :contributed)
|
|
|
|
render :json => wiki_page_json(@page, @current_user, session)
|
|
|
|
else
|
|
|
|
render :json => @page.errors.to_json, :status => :bad_request
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# @API Delete page
|
|
|
|
#
|
|
|
|
# Delete a wiki page
|
|
|
|
#
|
|
|
|
# @argument url the unique identifier for a page.
|
|
|
|
#
|
|
|
|
# @example_request
|
|
|
|
# curl -X DELETE -H 'Authorization: Bearer <token>' \
|
|
|
|
# https://<canvas>/api/v1/courses/123/pages/the-page-url
|
|
|
|
#
|
2013-05-17 05:02:04 +08:00
|
|
|
# @example_request
|
|
|
|
# curl -X DELETE -H 'Authorization: Bearer <token>' \
|
|
|
|
# https://<canvas>/api/v1/courses/123/front_page
|
|
|
|
#
|
2013-04-20 03:55:00 +08:00
|
|
|
# @returns Page
|
|
|
|
def destroy
|
|
|
|
if authorized_action(@page, @current_user, :delete)
|
2013-05-17 05:02:04 +08:00
|
|
|
get_front_page_params
|
2013-04-20 03:55:00 +08:00
|
|
|
@page.workflow_state = 'deleted'
|
|
|
|
@page.save!
|
2013-05-17 05:02:04 +08:00
|
|
|
process_front_page
|
2013-04-20 03:55:00 +08:00
|
|
|
render :json => wiki_page_json(@page, @current_user, session)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
|
|
|
def get_wiki_page
|
|
|
|
@wiki = @context.wiki
|
2013-05-17 05:02:04 +08:00
|
|
|
url = params[:url]
|
|
|
|
if url.blank?
|
|
|
|
if @wiki.has_front_page?
|
|
|
|
url = @wiki.get_front_page_url
|
|
|
|
else
|
|
|
|
render :status => 404, :json => { :message => t(:no_wiki_front_page, "No front page has been set") }
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
@page = @wiki.wiki_pages.not_deleted.find_by_url!(url)
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_front_page_params
|
|
|
|
@was_front_page = @page.front_page?
|
|
|
|
if params[:wiki_page] && params[:wiki_page].has_key?(:front_page)
|
|
|
|
@set_front_page = true
|
|
|
|
@set_as_front_page = value_to_boolean(params[:wiki_page].delete(:front_page))
|
|
|
|
end
|
2013-04-20 03:55:00 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def process_update_params
|
|
|
|
page_params = params[:wiki_page] || {}
|
2013-05-17 05:02:04 +08:00
|
|
|
|
2013-04-20 03:55:00 +08:00
|
|
|
if @page.grants_right?(@current_user, session, :update)
|
|
|
|
if page_params.has_key? :published
|
|
|
|
new_state = value_to_boolean(page_params.delete(:published)) ? 'active' : 'unpublished'
|
|
|
|
@page.workflow_state = new_state
|
|
|
|
end
|
|
|
|
|
|
|
|
roles = page_params[:editing_roles]
|
|
|
|
if roles.present?
|
2013-07-03 01:20:53 +08:00
|
|
|
page_params[:editing_roles] = roles.split(',').map(&:strip).reject{|role| !%w(teachers students members public).include?(role)}.join(',')
|
2013-04-20 03:55:00 +08:00
|
|
|
end
|
|
|
|
else
|
|
|
|
# editing_roles only allow changing content, not title or attributes
|
|
|
|
page_params.slice!(:body)
|
|
|
|
end
|
|
|
|
|
|
|
|
page_params[:user_id] = @current_user.id if @current_user
|
|
|
|
|
|
|
|
page_params
|
|
|
|
end
|
2013-05-17 05:02:04 +08:00
|
|
|
|
|
|
|
def process_front_page
|
|
|
|
if @set_front_page
|
|
|
|
if @set_as_front_page && !@page.front_page?
|
|
|
|
return @page.set_as_front_page!
|
|
|
|
elsif !@set_as_front_page
|
|
|
|
return @wiki.unset_front_page!
|
|
|
|
end
|
|
|
|
elsif @was_front_page
|
|
|
|
if @page.deleted?
|
|
|
|
return @wiki.unset_front_page!
|
|
|
|
elsif !@page.front_page?
|
|
|
|
# if url changes, keep as front page
|
|
|
|
return @page.set_as_front_page!
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
end
|
2013-04-20 03:55:00 +08:00
|
|
|
end
|