class WikiPagesController < ApplicationController def show render_wiki_page_or_404 WikiPage.find(params[:id]) end def show_by_title render_wiki_page_or_404 WikiPage.find_by(title: params[:title]) end def diff id = params[:id] from = params[:from] to = params[:to].presence return head :bad_request if id.blank? || from.blank? wiki_page_from = WikiPage.find(id) wiki_page_to = wiki_page_from.clone wiki_page_from.sha = from wiki_page_to.sha = to diffs = Diff::LCS.sdiff(wiki_page_from.body, wiki_page_to.body) diff_json = diffs.map { |change| case change.action when ?= { type: 'context', content: change.old_element } when ?| [{ type: 'removed', content: change.old_element }, { type: 'added', content: change.new_element }] when ?+ { type: 'added', content: change.new_element } when ?- { type: 'removed', content: change.old_element } end }.flatten.compact render json: { wiki_page_id: wiki_page_from.id, title: wiki_page_from.title, older_sha: wiki_page_from.sha, newer_sha: wiki_page_to.sha, diff: diff_json } end def create return head :unauthorized unless current_user return head :forbidden unless ['admin', 'member'].include?(current_user.role) wiki_page = WikiPage.new(title: params[:title], created_user: current_user, updated_user: current_user) if wiki_page.save wiki_page.set_body params[:body], user: current_user render json: wiki_page, status: :created else render json: { errors: wiki_page.errors.full_messages }, status: :unprocessable_entity end end def update return head :unauthorized unless current_user return head :forbidden unless current_user.member? title = params[:title] body = params[:body] return head :unprocessable_entity if title.blank? || body.blank? wiki_page = WikiPage.find(params[:id]) wiki_page.title = title wiki_page.updated_user = current_user wiki_page.set_body(body, user: current_user) wiki_page.save! head :ok end def search title = params[:title]&.strip q = WikiPage.all q = q.where('title LIKE ?', "%#{ WikiPage.sanitize_sql_like(title) }%") if title.present? render json: q.limit(20) end def changes id = params[:id] log = if id.present? wiki.page("#{ id }.md")&.versions else wiki.repo.log('main', nil) end return render json: [] unless log render json: log.map { |commit| wiki_page = WikiPage.find(commit.message.split(' ')[1].to_i) wiki_page.sha = commit.id next nil if wiki_page.sha.blank? user = User.find(commit.author.name.to_i) { sha: wiki_page.sha, pred: wiki_page.pred, succ: wiki_page.succ, wiki_page: wiki_page && { id: wiki_page.id, title: wiki_page.title }, user: user && { id: user.id, name: user.name }, change_type: commit.message.split(' ')[0].downcase[0...(-1)], timestamp: commit.authored_date } }.compact end private WIKI_PATH = Rails.root.join('wiki').to_s def wiki @wiki ||= Gollum::Wiki.new(WIKI_PATH) end def render_wiki_page_or_404 wiki_page return head :not_found unless wiki_page wiki_page.sha = params[:version].presence body = wiki_page.body sha = wiki_page.sha pred = wiki_page.pred succ = wiki_page.succ render json: wiki_page.as_json.merge(body:, sha:, pred:, succ:) end end