2019-09-02 14:32:57 +02:00
|
|
|
class PostsController < ApplicationController
|
2024-07-12 20:38:46 +02:00
|
|
|
before_action :authenticate_user!, only: [:update, :destroy]
|
|
|
|
|
before_action :authenticate_moderator, only: [:moderation]
|
|
|
|
|
before_action :authenticate_moderator_if_post_not_approved, only: [:show]
|
2024-05-03 18:11:07 +02:00
|
|
|
before_action :check_tenant_subscription, only: [:create, :update, :destroy]
|
2019-09-02 19:26:34 +02:00
|
|
|
|
2019-09-04 17:37:08 +02:00
|
|
|
def index
|
2024-02-15 22:30:41 +01:00
|
|
|
start_date = params[:start_date] ? Date.parse(params[:start_date]) : Date.parse('1970-01-01')
|
|
|
|
|
end_date = params[:end_date] ? Date.parse(params[:end_date]) : Date.today
|
|
|
|
|
|
2019-09-02 19:26:34 +02:00
|
|
|
posts = Post
|
2019-09-27 15:48:21 +02:00
|
|
|
.select(
|
|
|
|
|
:id,
|
|
|
|
|
:title,
|
2024-04-05 18:23:31 +02:00
|
|
|
:slug,
|
2019-09-27 15:48:21 +02:00
|
|
|
:description,
|
|
|
|
|
:post_status_id,
|
|
|
|
|
'COUNT(DISTINCT likes.id) AS likes_count',
|
|
|
|
|
'COUNT(DISTINCT comments.id) AS comments_count',
|
|
|
|
|
'((LOG(COUNT(DISTINCT likes.id) + 1) + LOG(COUNT(DISTINCT comments.id) + 1)) + (EXTRACT(EPOCH FROM posts.created_at) / 45000)) AS hotness',
|
|
|
|
|
"(SELECT COUNT(*) AS liked FROM likes WHERE likes.user_id=#{current_user ? current_user.id : -1} AND likes.post_id=posts.id)"
|
|
|
|
|
)
|
|
|
|
|
.left_outer_joins(:likes)
|
2019-09-21 11:17:58 +02:00
|
|
|
.left_outer_joins(:comments)
|
|
|
|
|
.group('posts.id')
|
2024-01-25 14:50:39 +01:00
|
|
|
.where(board_id: params[:board_id] || Board.first.id)
|
2024-02-15 22:30:41 +01:00
|
|
|
.where(created_at: start_date.beginning_of_day..end_date.end_of_day)
|
2024-07-12 20:38:46 +02:00
|
|
|
.where(approval_status: "approved")
|
2019-09-09 16:50:33 +02:00
|
|
|
.search_by_name_or_description(params[:search])
|
2024-01-26 17:43:24 +01:00
|
|
|
.order_by(params[:sort_by])
|
2019-09-04 21:12:07 +02:00
|
|
|
.page(params[:page])
|
2024-01-25 14:50:39 +01:00
|
|
|
|
2024-07-12 20:38:46 +02:00
|
|
|
# apply post status filter if present
|
|
|
|
|
posts = posts.where(post_status_id: params[:post_status_ids].map { |id| id == "0" ? nil : id }) if params[:post_status_ids].present?
|
2019-09-02 19:26:34 +02:00
|
|
|
|
2019-09-04 15:24:15 +02:00
|
|
|
render json: posts
|
2019-09-02 19:26:34 +02:00
|
|
|
end
|
2019-09-02 14:32:57 +02:00
|
|
|
|
|
|
|
|
def create
|
2024-07-12 20:38:46 +02:00
|
|
|
if anti_spam_checks || invalid_anonymous_submission
|
|
|
|
|
render json: {
|
|
|
|
|
error: t('errors.unknown')
|
|
|
|
|
}, status: :unprocessable_entity
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# handle anonymous feedback
|
|
|
|
|
approval_status = "pending"
|
|
|
|
|
is_anonymous = params[:post][:is_anonymous]
|
|
|
|
|
|
|
|
|
|
if Current.tenant.tenant_setting.feedback_approval_policy == "never_require_approval" ||
|
|
|
|
|
(Current.tenant.tenant_setting.feedback_approval_policy == "anonymous_require_approval" && !is_anonymous) ||
|
|
|
|
|
(user_signed_in? && current_user.moderator?)
|
|
|
|
|
approval_status = "approved"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
@post = Post.new(approval_status: approval_status)
|
|
|
|
|
@post.assign_attributes(post_create_params(is_anonymous: is_anonymous))
|
2019-09-02 14:32:57 +02:00
|
|
|
|
2025-01-28 16:55:48 +01:00
|
|
|
# handle attachments
|
2025-02-05 15:51:37 +01:00
|
|
|
if Current.tenant.tenant_setting.allow_attachment_upload && params[:post][:attachments].present? && !is_anonymous
|
2025-01-28 16:55:48 +01:00
|
|
|
@post.attachments.attach(params[:post][:attachments])
|
|
|
|
|
end
|
|
|
|
|
|
2022-06-22 10:17:42 +02:00
|
|
|
if @post.save
|
2024-07-12 20:38:46 +02:00
|
|
|
Follow.create(post_id: @post.id, user_id: current_user.id) unless is_anonymous
|
2022-05-28 11:03:36 +02:00
|
|
|
|
2022-06-22 10:17:42 +02:00
|
|
|
render json: @post, status: :created
|
2019-09-02 14:32:57 +02:00
|
|
|
else
|
2019-09-04 15:24:15 +02:00
|
|
|
render json: {
|
2022-06-22 10:17:42 +02:00
|
|
|
error: @post.errors.full_messages
|
2019-09-04 15:24:15 +02:00
|
|
|
}, status: :unprocessable_entity
|
2019-09-02 14:32:57 +02:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2019-09-12 15:51:45 +02:00
|
|
|
def show
|
2022-06-22 10:17:42 +02:00
|
|
|
@post = Post
|
2024-04-05 18:23:31 +02:00
|
|
|
.friendly
|
2022-06-22 10:17:42 +02:00
|
|
|
.select(
|
|
|
|
|
:id,
|
|
|
|
|
:title,
|
2024-04-05 18:23:31 +02:00
|
|
|
:slug,
|
2022-06-22 10:17:42 +02:00
|
|
|
:description,
|
2024-07-12 20:38:46 +02:00
|
|
|
:approval_status,
|
2022-06-22 10:17:42 +02:00
|
|
|
:board_id,
|
|
|
|
|
:user_id,
|
|
|
|
|
:post_status_id,
|
|
|
|
|
:created_at,
|
|
|
|
|
:updated_at,
|
|
|
|
|
'users.email as user_email',
|
|
|
|
|
'users.full_name as user_full_name'
|
|
|
|
|
)
|
2024-07-12 20:38:46 +02:00
|
|
|
.eager_load(:user) # left outer join
|
2022-06-22 10:17:42 +02:00
|
|
|
.find(params[:id])
|
2025-01-28 16:55:48 +01:00
|
|
|
|
2019-09-19 14:00:34 +02:00
|
|
|
@post_statuses = PostStatus.select(:id, :name, :color).order(order: :asc)
|
2019-09-27 11:40:33 +02:00
|
|
|
@board = @post.board
|
2019-09-12 15:51:45 +02:00
|
|
|
|
2024-01-26 17:35:00 +01:00
|
|
|
@page_title = @post.title.length > 60 ? @post.title.slice(0, 60) + "..." : @post.title
|
|
|
|
|
|
2019-09-12 15:51:45 +02:00
|
|
|
respond_to do |format|
|
|
|
|
|
format.html
|
|
|
|
|
|
2025-02-04 14:29:33 +01:00
|
|
|
format.json { render json: @post.as_json.merge(attachment_urls: @post.attachments.order(:created_at).map { |attachment| attachment.blob.url }) }
|
2019-09-12 15:51:45 +02:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def update
|
2022-06-22 10:17:42 +02:00
|
|
|
@post = Post.find(params[:id])
|
|
|
|
|
authorize @post
|
2022-05-28 11:03:36 +02:00
|
|
|
|
2022-06-22 10:17:42 +02:00
|
|
|
@post.assign_attributes(post_update_params)
|
2019-09-12 15:51:45 +02:00
|
|
|
|
2025-02-04 14:29:33 +01:00
|
|
|
# handle attachment deletion
|
|
|
|
|
if params[:post][:attachments_to_delete].present? && @post.attachments.attached?
|
|
|
|
|
@post.attachments.order(:created_at).each_with_index do |attachment, index|
|
2025-02-04 14:54:59 +01:00
|
|
|
attachment.purge if params[:post][:attachments_to_delete].include?(index.to_s)
|
2025-02-04 14:29:33 +01:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2025-02-04 14:54:59 +01:00
|
|
|
# handle attachments
|
|
|
|
|
if Current.tenant.tenant_setting.allow_attachment_upload && params[:post][:attachments].present?
|
|
|
|
|
@post.attachments.attach(params[:post][:attachments])
|
|
|
|
|
end
|
|
|
|
|
|
2022-06-22 10:17:42 +02:00
|
|
|
if @post.save
|
|
|
|
|
if @post.post_status_id_previously_changed?
|
2024-11-08 16:40:53 +01:00
|
|
|
ExecutePostStatusChangeLogicWorkflow.new(
|
2022-05-28 11:03:36 +02:00
|
|
|
user_id: current_user.id,
|
2024-11-08 16:40:53 +01:00
|
|
|
post: @post,
|
2022-06-22 10:17:42 +02:00
|
|
|
post_status_id: @post.post_status_id
|
2024-11-08 16:40:53 +01:00
|
|
|
).run
|
2022-05-28 11:03:36 +02:00
|
|
|
end
|
|
|
|
|
|
2025-02-04 14:29:33 +01:00
|
|
|
render json: @post.as_json.merge(attachment_urls: @post.attachments.order(:created_at).map { |attachment| attachment.blob.url })
|
2019-09-12 15:51:45 +02:00
|
|
|
else
|
|
|
|
|
render json: {
|
2022-06-22 10:17:42 +02:00
|
|
|
error: @post.errors.full_messages
|
|
|
|
|
}, status: :unprocessable_entity
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def destroy
|
|
|
|
|
@post = Post.find(params[:id])
|
|
|
|
|
authorize @post
|
|
|
|
|
|
|
|
|
|
if @post.destroy
|
|
|
|
|
render json: {
|
|
|
|
|
id: @post.id,
|
|
|
|
|
}, status: :accepted
|
|
|
|
|
else
|
|
|
|
|
render json: {
|
|
|
|
|
error: @post.errors.full_messages
|
2019-09-12 15:51:45 +02:00
|
|
|
}, status: :unprocessable_entity
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2024-07-12 20:38:46 +02:00
|
|
|
# Returns a list of posts for moderation in JSON
|
|
|
|
|
def moderation
|
|
|
|
|
posts = Post
|
|
|
|
|
.select(
|
|
|
|
|
:id,
|
|
|
|
|
:title,
|
|
|
|
|
:description,
|
|
|
|
|
:slug,
|
|
|
|
|
:approval_status,
|
|
|
|
|
:user_id,
|
|
|
|
|
:board_id,
|
|
|
|
|
:created_at,
|
2025-01-09 10:55:44 +01:00
|
|
|
'users.id as user_id', # required for avatar_url
|
2024-07-12 20:38:46 +02:00
|
|
|
'users.email as user_email',
|
|
|
|
|
'users.full_name as user_full_name'
|
|
|
|
|
)
|
|
|
|
|
.eager_load(:user)
|
|
|
|
|
.where(approval_status: ["pending", "rejected"])
|
|
|
|
|
.order_by(created_at: :desc)
|
|
|
|
|
.limit(100)
|
2025-01-09 10:55:44 +01:00
|
|
|
.includes(user: { avatar_attachment: :blob }) # Preload avatars
|
|
|
|
|
|
|
|
|
|
posts = posts.map do |post|
|
2025-01-23 12:47:35 +01:00
|
|
|
user_avatar_url = post.user.avatar.attached? ? post.user.avatar.blob.url : nil
|
2025-01-09 10:55:44 +01:00
|
|
|
post.attributes.merge(user_avatar: user_avatar_url)
|
|
|
|
|
end
|
2024-07-12 20:38:46 +02:00
|
|
|
|
|
|
|
|
render json: posts
|
|
|
|
|
end
|
|
|
|
|
|
2019-09-02 14:32:57 +02:00
|
|
|
private
|
2024-07-12 20:38:46 +02:00
|
|
|
|
|
|
|
|
def authenticate_moderator_if_post_not_approved
|
|
|
|
|
post = Post.friendly.find(params[:id])
|
|
|
|
|
authenticate_moderator unless post.approval_status == "approved"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def anti_spam_checks
|
2024-07-16 17:30:23 +02:00
|
|
|
params[:post][:dnf1] != "" || params[:post][:dnf2] != "" || Time.now.to_i - params[:post][:form_rendered_at] < 2
|
2024-07-12 20:38:46 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def invalid_anonymous_submission
|
|
|
|
|
(params[:post][:is_anonymous] == false && !user_signed_in?) || (params[:post][:is_anonymous] == true && Current.tenant.tenant_setting.allow_anonymous_feedback == false)
|
|
|
|
|
end
|
2019-09-03 12:58:44 +02:00
|
|
|
|
2024-07-12 20:38:46 +02:00
|
|
|
def post_create_params(is_anonymous: false)
|
2019-09-04 15:24:15 +02:00
|
|
|
params
|
|
|
|
|
.require(:post)
|
2022-06-22 10:17:42 +02:00
|
|
|
.permit(policy(@post).permitted_attributes_for_create)
|
2024-07-12 20:38:46 +02:00
|
|
|
.merge(user_id: is_anonymous ? nil : current_user.id)
|
2019-09-02 14:32:57 +02:00
|
|
|
end
|
2022-05-28 11:03:36 +02:00
|
|
|
|
2022-06-22 10:17:42 +02:00
|
|
|
def post_update_params
|
|
|
|
|
params
|
|
|
|
|
.require(:post)
|
2025-02-04 14:29:33 +01:00
|
|
|
.permit(
|
|
|
|
|
policy(@post)
|
|
|
|
|
.permitted_attributes_for_update
|
|
|
|
|
.concat([{ additional_params: [:attachments_to_delete] }])
|
|
|
|
|
)
|
2022-05-28 11:03:36 +02:00
|
|
|
end
|
2019-09-02 14:32:57 +02:00
|
|
|
end
|