This commit is contained in:
2025-12-29 06:15:13 +09:00
parent 01e99b7f15
commit 2832d0a6ca
6 changed files with 324 additions and 125 deletions
@@ -1,8 +1,8 @@
class WikiPagesController < ApplicationController
def index
wiki_pages = WikiPage.all
rescue_from Wiki::Commit::Conflict, with: :render_wiki_conflict
render json: wiki_pages
def index
render json: WikiPage.all
end
def show
@@ -35,12 +35,13 @@ class WikiPagesController < ApplicationController
to = params[:to].presence
return head :bad_request if id.blank? || from.blank?
wiki_page_from = WikiPage.find(id)
wiki_page_to = WikiPage.find(id)
wiki_page_from.sha = from
wiki_page_to.sha = to
page = WikiPage.find(id)
diffs = Diff::LCS.sdiff(wiki_page_from.body, wiki_page_to.body)
from_rev = page.wiki_revisions.find(from)
to_rev = to ? page.wiki_revisions.find(to) : page.current_revision
return head :unprocessable_entity if !(from_rev&.content?) || !(to_rev&.content?)
diffs = Diff::LCS.sdiff(from_rev.body.lines, to_rev.body.lines)
diff_json = diffs.map { |change|
case change.action
when ?=
@@ -55,23 +56,32 @@ class WikiPagesController < ApplicationController
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 }
render json: { wiki_page_id: page.id,
title: page.title,
older_revision_id: from_rev.id,
newer_revision_id: to_rev.id,
diff: diff_json }
end
def create
return head :unauthorized unless current_user
return head :forbidden unless ['admin', 'member'].include?(current_user.role)
return head :forbidden unless current_user.member?
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
title = params[:title]&.strip
body = params[:body].to_s
return head :unprocessable_entity if title.blank? || body.blank?
page = WikiPage.new(title:)
if page.save
message = params[:message].presence
Wiki::Commit.content!(page:, body:, created_user: current_user, message:)
render json: page, status: :created
else
render json: { errors: wiki_page.errors.full_messages }, status: :unprocessable_entity
render json: { errors: page.errors.full_messages },
status: :unprocessable_entity
end
end
@@ -79,16 +89,19 @@ class WikiPagesController < ApplicationController
return head :unauthorized unless current_user
return head :forbidden unless current_user.member?
title = params[:title]
body = params[:body]
title = params[:title]&.strip
body = params[:body].to_s
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!
page = WikiPage.find(params[:id])
if params[:title].present? && params[:title].strip != page.title
return head :unprocessable_entity
end
message = params[:message].presence
Wiki::Commit.content!(page:, body:, created_user: current_user, message:)
head :ok
end
@@ -97,55 +110,73 @@ class WikiPagesController < ApplicationController
title = params[:title]&.strip
q = WikiPage.all
q = q.where('title LIKE ?', "%#{ WikiPage.sanitize_sql_like(title) }%") if title.present?
if title.present?
q = q.where('title LIKE ?', "%#{ WikiPage.sanitize_sql_like(title) }%")
end
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
id = params[:id].presence
q = WikiRevision.includes(:wiki_page, :created_user).order(id: :desc)
q = q.where(wiki_page_id: id) if id
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 }
render json: q.limit(200).map { |rev|
{ revision_id: rev.id,
pred: rev.base_revision_id,
succ: nil,
wiki_page: { id: rev.wiki_page_id, title: rev.wiki_page.title },
user: { id: rev.created_user.id, name: rev.created_user.name },
kind: rev.kind,
message: rev.message,
timestamp: rev.created_at }
}.compact
end
private
WIKI_PATH = Rails.root.join('wiki').to_s
def render_wiki_page_or_404 page
return head :not_found unless page
def wiki
@wiki ||= Gollum::Wiki.new(WIKI_PATH)
if params[:version].present?
rev = page.wiki_revisions.find_by(id: params[:version])
return head :not_found unless rev
if rev.redirect?
return (
redirect_to wiki_page_by_title_path(title: rev.redirect_page.title),
status: :moved_permanently)
end
body = rev.body
revision_id = rev.id
pred = page.pred_revision_id(revision_id)
succ = page.succ_revision_id(revision_id)
return render json: page.as_json.merge(body:, revision_id:, pred:, succ:)
end
rev = page.current_revision
unless rev
return render json: page.as_json.merge(body: nil, revision_id: nil, pred: nil, succ: nil)
end
if rev.redirect?
return (
redirect_to wiki_page_by_title_path(title: rev.redirect_page.title),
status: :moved_permanently)
end
body = rev.body
revision_id = rev.id
pred = page.pred_revision_id(revision_id)
succ = page.succ_revision_id(revision_id)
render json: page.as_json.merge(body:, revision_id:, pred:, succ:)
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:)
def render_wiki_conflict err
render json: { error: 'conflict', message: err.message }, status: :conflict
end
end