ぼざクリタグ広場 https://hub.nizika.monster
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

214 lines
6.0 KiB

  1. class WikiPagesController < ApplicationController
  2. rescue_from Wiki::Commit::Conflict, with: :render_wiki_conflict
  3. def index
  4. title = params[:title].to_s.strip
  5. if title.blank?
  6. return render json: WikiPageRepr.base(WikiPage.joins(:tag_name).includes(:tag_name))
  7. end
  8. q = WikiPage.joins(:tag_name).includes(:tag_name)
  9. .where('tag_names.name LIKE ?', "%#{ WikiPage.sanitize_sql_like(title) }%")
  10. render json: WikiPageRepr.base(q.limit(20))
  11. end
  12. def show
  13. page = WikiPage.joins(:tag_name)
  14. .includes(:tag_name)
  15. .find_by(id: params[:id])
  16. render_wiki_page_or_404 page
  17. end
  18. def show_by_title
  19. title = params[:title].to_s.strip
  20. page = WikiPage.joins(:tag_name)
  21. .includes(:tag_name)
  22. .find_by(tag_name: { name: title })
  23. render_wiki_page_or_404 page
  24. end
  25. def exists
  26. if WikiPage.exists?(id: params[:id])
  27. head :no_content
  28. else
  29. head :not_found
  30. end
  31. end
  32. def exists_by_title
  33. title = params[:title].to_s.strip
  34. if WikiPage.joins(:tag_name).exists?(tag_names: { name: title })
  35. head :no_content
  36. else
  37. head :not_found
  38. end
  39. end
  40. def diff
  41. id = params[:id]
  42. return head :bad_request if id.blank?
  43. from = params[:from].presence
  44. to = params[:to].presence
  45. page = WikiPage.joins(:tag_name).includes(:tag_name).find(id)
  46. from_rev = from && page.wiki_revisions.find(from)
  47. to_rev = to ? page.wiki_revisions.find(to) : page.current_revision
  48. if ((from_rev && !(from_rev.content?)) || !(to_rev&.content?))
  49. return head :unprocessable_entity
  50. end
  51. diffs = Diff::LCS.sdiff(from_rev&.body&.lines || [], to_rev.body.lines)
  52. diff_json = diffs.map { |change|
  53. case change.action
  54. when ?=
  55. { type: 'context', content: change.old_element }
  56. when ?!
  57. [{ type: 'removed', content: change.old_element },
  58. { type: 'added', content: change.new_element }]
  59. when ?+
  60. { type: 'added', content: change.new_element }
  61. when ?-
  62. { type: 'removed', content: change.old_element }
  63. end
  64. }.flatten.compact
  65. render json: { wiki_page_id: page.id,
  66. title: page.title,
  67. older_revision_id: from_rev&.id,
  68. newer_revision_id: to_rev.id,
  69. diff: diff_json }
  70. end
  71. def create
  72. return head :unauthorized unless current_user
  73. return head :forbidden unless current_user.gte_member?
  74. title = params[:title].to_s.strip
  75. body = params[:body].to_s
  76. message = params[:message].presence
  77. return head :unprocessable_entity if title.blank? || body.blank?
  78. tag_name = TagName.find_undiscard_or_create_by!(name: title)
  79. page =
  80. Wiki::Commit.create_content!(
  81. tag_name:,
  82. body:,
  83. created_by_user: current_user,
  84. message:)
  85. render json: WikiPageRepr.base(page), status: :created
  86. rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
  87. head :unprocessable_entity
  88. end
  89. def update
  90. return head :unauthorized unless current_user
  91. return head :forbidden unless current_user.gte_member?
  92. title = params[:title].to_s.strip
  93. body = params[:body].to_s
  94. return head :unprocessable_entity if title.blank? || body.blank?
  95. page = WikiPage.find(params[:id])
  96. base_revision_id = params[:base_revision_id].presence
  97. ApplicationRecord.transaction do
  98. page.lock!
  99. old_title = page.title
  100. tag = Tag.find_by(tag_name_id: page.tag_name_id)
  101. if tag && title != old_title
  102. TagVersioning.ensure_snapshot!(tag, created_by_user: current_user)
  103. end
  104. page.tag_name.update!(name: title) if title != old_title
  105. message = params[:message].presence
  106. Wiki::Commit.content!(page:,
  107. body:,
  108. created_user: current_user,
  109. message:,
  110. base_revision_id:)
  111. if tag && title != old_title
  112. tag.reload
  113. TagVersionRecorder.record!(tag:, event_type: :update, created_by_user: current_user)
  114. end
  115. end
  116. message = params[:message].presence
  117. Wiki::Commit.content!(page:,
  118. body:,
  119. created_user: current_user,
  120. message:,
  121. base_revision_id:)
  122. render json: WikiPageRepr.base(page).merge(body:)
  123. end
  124. def search
  125. index
  126. end
  127. def changes
  128. id = params[:id].presence
  129. q = WikiRevision.joins(wiki_page: :tag_name)
  130. .includes(:created_user, wiki_page: :tag_name)
  131. .order(id: :desc)
  132. q = q.where(wiki_page_id: id) if id
  133. render json: q.limit(200).map { |rev|
  134. { revision_id: rev.id,
  135. pred: rev.base_revision_id,
  136. succ: nil,
  137. wiki_page: { id: rev.wiki_page_id, title: rev.wiki_page.title },
  138. user: rev.created_user && { id: rev.created_user.id, name: rev.created_user.name },
  139. kind: rev.kind,
  140. message: rev.message,
  141. timestamp: rev.created_at }
  142. }.compact
  143. end
  144. private
  145. def render_wiki_page_or_404 page
  146. return head :not_found unless page
  147. rev = find_revision(page)
  148. return head :not_found unless rev
  149. if rev.redirect?
  150. return (
  151. redirect_to wiki_page_by_title_path(title: rev.redirect_page.title),
  152. status: :moved_permanently)
  153. end
  154. body = rev.body
  155. revision_id = rev.id
  156. pred = page.pred_revision_id(revision_id)
  157. succ = page.succ_revision_id(revision_id)
  158. updated_at = rev.created_at
  159. render json: WikiPageRepr.base(page).merge(body:, revision_id:, pred:, succ:, updated_at:)
  160. end
  161. def find_revision page
  162. if params[:version].present?
  163. page.wiki_revisions.find_by(id: params[:version])
  164. else
  165. page.current_revision
  166. end
  167. end
  168. def render_wiki_conflict err
  169. render json: { error: 'conflict', message: err.message }, status: :conflict
  170. end
  171. end