ぼざクリタグ広場 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.
 
 
 
 
 
 

191 lines
5.1 KiB

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