otwarchive-symphonyarchive/app/controllers/collections_controller.rb

215 lines
7.7 KiB
Ruby
Raw Normal View History

2026-03-11 22:22:11 +00:00
class CollectionsController < ApplicationController
before_action :users_only, only: [:new, :edit, :create, :update]
before_action :load_collection_from_id, only: [:show, :edit, :update, :destroy, :confirm_delete]
before_action :collection_owners_only, only: [:edit, :update, :destroy, :confirm_delete]
before_action :check_user_status, only: [:new, :create, :edit, :update, :destroy]
before_action :validate_challenge_type
before_action :check_parent_visible, only: [:index]
cache_sweeper :collection_sweeper
# Lazy fix to prevent passing unsafe values to eval via challenge_type
# In both CollectionsController#create and CollectionsController#update there are a vulnerable usages of eval
# For now just make sure the values passed to it are safe
def validate_challenge_type
if params[:challenge_type] and not ["", "GiftExchange", "PromptMeme"].include?(params[:challenge_type])
return render status: :bad_request, text: "invalid challenge_type"
end
end
def load_collection_from_id
@collection = Collection.find_by(name: params[:id])
unless @collection
raise ActiveRecord::RecordNotFound, "Couldn't find collection named '#{params[:id]}'"
end
end
def check_parent_visible
return unless params[:work_id] && (@work = Work.find_by(id: params[:work_id]))
check_visibility_for(@work)
end
def index
if params[:work_id]
@work = Work.find(params[:work_id])
@collections = @work.approved_collections
.by_title
.for_blurb
.paginate(page: params[:page])
elsif params[:collection_id]
@collection = Collection.find_by!(name: params[:collection_id])
@collections = @collection.children
.by_title
.for_blurb
.paginate(page: params[:page])
@page_subtitle = t(".subcollections_page_title", collection_title: @collection.title)
elsif params[:user_id]
@user = User.find_by!(login: params[:user_id])
@collections = @user.maintained_collections
.by_title
.for_blurb
.paginate(page: params[:page])
@page_subtitle = ts("%{username} - Collections", username: @user.login)
else
@sort_and_filter = true
params[:collection_filters] ||= {}
params[:sort_column] = "collections.created_at" if !valid_sort_column(params[:sort_column], 'collection')
params[:sort_direction] = 'DESC' if !valid_sort_direction(params[:sort_direction])
sort = params[:sort_column] + " " + params[:sort_direction]
@collections = Collection.sorted_and_filtered(sort, params[:collection_filters], params[:page])
end
end
# display challenges that are currently taking signups
def list_challenges
@page_subtitle = "Open Challenges"
@hide_dashboard = true
@challenge_collections = (Collection.signup_open("GiftExchange").limit(15) + Collection.signup_open("PromptMeme").limit(15))
end
def list_ge_challenges
@page_subtitle = "Open Gift Exchange Challenges"
@challenge_collections = Collection.signup_open("GiftExchange").limit(15)
end
def list_pm_challenges
@page_subtitle = "Open Prompt Meme Challenges"
@challenge_collections = Collection.signup_open("PromptMeme").limit(15)
end
def show
@page_subtitle = @collection.title
if @collection.collection_preference.show_random? || params[:show_random]
# show a random selection of works/bookmarks
@works = WorkQuery.new(
collection_ids: [@collection.id], show_restricted: is_registered_user?
).sample(count: ArchiveConfig.NUMBER_OF_ITEMS_VISIBLE_IN_DASHBOARD)
@bookmarks = BookmarkQuery.new(
collection_ids: [@collection.id], show_restricted: is_registered_user?
).sample(count: ArchiveConfig.NUMBER_OF_ITEMS_VISIBLE_IN_DASHBOARD)
else
# show recent
@works = WorkQuery.new(
collection_ids: [@collection.id], show_restricted: is_registered_user?,
sort_column: "revised_at",
per_page: ArchiveConfig.NUMBER_OF_ITEMS_VISIBLE_IN_DASHBOARD
).search_results
@bookmarks = BookmarkQuery.new(
collection_ids: [@collection.id], show_restricted: is_registered_user?,
sort_column: "created_at",
per_page: ArchiveConfig.NUMBER_OF_ITEMS_VISIBLE_IN_DASHBOARD
).search_results
end
end
def new
@hide_dashboard = true
@collection = Collection.new
if params[:collection_id] && (@collection_parent = Collection.find_by(name: params[:collection_id]))
@collection.parent_name = @collection_parent.name
end
end
def edit
end
def create
@hide_dashboard = true
@collection = Collection.new(collection_params)
# add the owner
owner_attributes = []
(params[:owner_pseuds] || [current_user.default_pseud_id]).each do |pseud_id|
pseud = Pseud.find(pseud_id)
owner_attributes << {pseud: pseud, participant_role: CollectionParticipant::OWNER} if pseud
end
@collection.collection_participants.build(owner_attributes)
if @collection.save
flash[:notice] = ts('Collection was successfully created.')
unless params[:challenge_type].blank?
if params[:challenge_type] == "PromptMeme"
redirect_to new_collection_prompt_meme_path(@collection) and return
elsif params[:challenge_type] == "GiftExchange"
redirect_to new_collection_gift_exchange_path(@collection) and return
end
else
redirect_to collection_path(@collection)
end
else
@challenge_type = params[:challenge_type]
render action: "new"
end
end
def update
if @collection.update(collection_params)
flash[:notice] = ts('Collection was successfully updated.')
if params[:challenge_type].blank?
if @collection.challenge
# trying to destroy an existing challenge
flash[:error] = ts("Note: if you want to delete an existing challenge, please do so on the challenge page.")
end
else
if @collection.challenge
if @collection.challenge.class.name != params[:challenge_type]
flash[:error] = ts("Note: if you want to change the type of challenge, first please delete the existing challenge on the challenge page.")
else
if params[:challenge_type] == "PromptMeme"
redirect_to edit_collection_prompt_meme_path(@collection) and return
elsif params[:challenge_type] == "GiftExchange"
redirect_to edit_collection_gift_exchange_path(@collection) and return
end
end
else
if params[:challenge_type] == "PromptMeme"
redirect_to new_collection_prompt_meme_path(@collection) and return
elsif params[:challenge_type] == "GiftExchange"
redirect_to new_collection_gift_exchange_path(@collection) and return
end
end
end
redirect_to collection_path(@collection)
else
render action: "edit"
end
end
def confirm_delete
end
def destroy
@hide_dashboard = true
@collection = Collection.find_by(name: params[:id])
begin
@collection.destroy
flash[:notice] = ts("Collection was successfully deleted.")
rescue
flash[:error] = ts("We couldn't delete that right now, sorry! Please try again later.")
end
redirect_to(collections_path)
end
private
def collection_params
params.require(:collection).permit(
:name, :title, :email, :header_image_url, :description,
:parent_name, :challenge_type, :icon, :delete_icon,
:icon_alt_text, :icon_comment_text,
collection_profile_attributes: [
:id, :intro, :faq, :rules,
:gift_notification, :assignment_notification
],
collection_preference_attributes: [
:id, :moderated, :closed, :unrevealed, :anonymous,
:gift_exchange, :show_random, :prompt_meme, :email_notify
]
)
end
end