325 lines
11 KiB
Ruby
325 lines
11 KiB
Ruby
class PackagesController < ApplicationController
|
|
|
|
protect_from_forgery :except => :legacy_uploadfile
|
|
|
|
def list
|
|
@packages = query_packages.paginate(page: params[:page], per_page: 6)
|
|
end
|
|
|
|
def grid
|
|
@packages = query_packages.paginate(page: params[:page], per_page: 24)
|
|
end
|
|
|
|
def details
|
|
# TODO: Get only screenshots visible to the user (admin or owner or approved)
|
|
@package = Package.find_by(name: params[:name])
|
|
|
|
unless @package
|
|
@packagename = params[:name]
|
|
render 'notfound'
|
|
end
|
|
end
|
|
|
|
# Show upload form for new images
|
|
def upload
|
|
@package = Package.find_by!(name: params[:name])
|
|
end
|
|
|
|
# POST target of the screenshots upload form.
|
|
# Receives uploaded images. Checks if they are valid. Asks for description.
|
|
# This action saves the screenshots already if they are valid. The user is
|
|
# then given the chance to comment on and delete the screenshots again.
|
|
def upload_receive
|
|
# Create a pseudo user account for the user.
|
|
# The user won't know that an account is created.
|
|
# But this makes it easier to track who screenshots belong to.
|
|
create_pseudo_user unless user_signed_in?
|
|
|
|
@package = Package.find_by!(name: params[:name])
|
|
@valid_images = []
|
|
@invalid_images = []
|
|
|
|
# If Javascript is disabled a user may submit an empty selection of images.
|
|
if params[:file] == nil
|
|
flash[:error] = "You have not selected any images."
|
|
redirect_to upload_path
|
|
return
|
|
end
|
|
|
|
params[:file].each do |img|
|
|
new_screenshot = @package.screenshots.new(image: img)
|
|
|
|
# Check if the image was valid
|
|
if new_screenshot.valid?
|
|
new_screenshot.uploaderhash = session[:token]
|
|
new_screenshot.uploaderip = session[:ip]
|
|
new_screenshot.version = @package.version
|
|
new_screenshot.user = current_user
|
|
|
|
# TODO: must it be moderated first?
|
|
|
|
new_screenshot.save
|
|
Log.log "Screenshot #{new_screenshot.id} uploaded successfully from #{session[:ip]}. User has token #{session[:token]} or is #{current_user}"
|
|
|
|
if current_user.is_admin?
|
|
Log.log "Admin upload is automatically approved."
|
|
new_screenshot.approve_screenshot!
|
|
end
|
|
|
|
@valid_images.push new_screenshot
|
|
else
|
|
Log.log "Screenshot #{new_screenshot.image_file_name} invalid (#{new_screenshot.errors[:image]})."
|
|
@invalid_images.push new_screenshot
|
|
end
|
|
end
|
|
|
|
errors = []
|
|
@invalid_images.each do |image|
|
|
# errors << "The image #{image.image_file_name} #{image.errors[:image].join(' and ')}."
|
|
errors << "The image #{image.image_file_name} is not valid."
|
|
flash[:error] = errors.join(" ")
|
|
end
|
|
|
|
# Redirect back to upload form if all uploads were invalid
|
|
unless @valid_images.any?
|
|
Log.log "No valid images uploaded. Back to upload form."
|
|
redirect_to(upload_path, error: errors) and return
|
|
end
|
|
|
|
# Show a list of invalid uploads by default. Or redirect to the review page
|
|
# if all uploads were okay.
|
|
# redirect_to upload_review_path unless @invalid_images
|
|
|
|
# TODO
|
|
# if @invalid_images…
|
|
# ' #{image.image_file_name} (#{image.errors[:image].join(' and ')})
|
|
|
|
redirect_to package_path
|
|
# render :details
|
|
end
|
|
|
|
# Legacy action to upload an image along with metadata.
|
|
# This was used in Debshots 1.x as the default upload method.
|
|
# This method allows that old-style way to upload screenshots.
|
|
# It is probably used by screenshotting tools.
|
|
#
|
|
# Parameters:
|
|
# - packagename
|
|
# - version
|
|
# - description
|
|
# - file
|
|
def legacy_uploadfile
|
|
@package = Package.find_by!(name: params[:packagename])
|
|
|
|
new_screenshot = @package.screenshots.new(image: params[:file])
|
|
|
|
# Check if the image was valid
|
|
if new_screenshot.valid?
|
|
# new_screenshot.uploaderhash = session[:token]
|
|
new_screenshot.uploaderip = session[:ip]
|
|
new_screenshot.version = @package.version
|
|
new_screenshot.save
|
|
Log.log "Screenshot #{new_screenshot.id} uploaded successfully from legacy upload form."
|
|
redirect_to package_path(params[:packagename])
|
|
else
|
|
Log.log "Screenshot upload rejected. Errors: #{new_screenshot.errors.to_a}"
|
|
head :not_acceptable
|
|
end
|
|
end
|
|
|
|
def delete_screenshot
|
|
# Is the user allowed to delete the screenshot?
|
|
@screenshot = Screenshot.find(params[:id])
|
|
|
|
# Check if the user is allowed to change this screenshot
|
|
# - Is this the user's own screenshot? (anonymous)
|
|
if @screenshot.user == current_user or current_user.is_admin?
|
|
logger.debug "User #{current_user} deletes screenshot #{@screenshot}"
|
|
@screenshot.destroy
|
|
flash['notice'] = "Screenshot deleted."
|
|
redirect_back(fallback_location: package_path(name: @screenshot.package.name))
|
|
else
|
|
head :forbidden
|
|
end
|
|
end
|
|
|
|
def approve_screenshot
|
|
@screenshot = Screenshot.find(params[:id])
|
|
@screenshot.approve_screenshot!
|
|
flash['notice'] = "Screenshot approved."
|
|
redirect_back(fallback_location: package_path(name: @screenshot.package.name))
|
|
end
|
|
|
|
# Returns a 160x120 thumbnail image if posssible.
|
|
# If the package is not found it returns a dummy image along with status 404.
|
|
# If the package is found but has no screenshots then it also returns a
|
|
# dummy image along with status 404.
|
|
def thumbnail
|
|
@package = Package.find_by(name: params[:name])
|
|
unless @package
|
|
thumbnail404
|
|
return
|
|
end
|
|
|
|
# Called as /thumbnail-with-version/:name/:version
|
|
if params[:version]
|
|
@screenshot = @package.best_screenshot_for_version(params[:version])
|
|
# Called as /thumbnail/:name
|
|
else
|
|
@screenshot = @package.screenshots.first
|
|
end
|
|
|
|
# Return a 404 if the package has no screenshots or the image was not found
|
|
unless @screenshot and @screenshot.image.path
|
|
thumbnail404
|
|
return
|
|
end
|
|
|
|
# Send the thumbnail (uses X-Sendfile or similar if possible)
|
|
send_file @screenshot.image.path(:thumb), type: "image/png", disposition: 'inline'
|
|
end
|
|
|
|
# Returns a large screenshot image if posssible.
|
|
# If the package is not found it returns a dummy image along with status 404.
|
|
# If the package is found but has no screenshots then it also returns a
|
|
# dummy image along with status 404.
|
|
def screenshot
|
|
@package = Package.find_by(name: params[:name])
|
|
unless @package
|
|
screenshot404
|
|
return
|
|
end
|
|
|
|
# Called as /thumbnail-with-version/:name/:version
|
|
if params[:version]
|
|
@screenshot = @package.best_screenshot_for_version(params[:version])
|
|
# Called as /thumbnail/:name
|
|
else
|
|
@screenshot = @package.screenshots.first
|
|
end
|
|
|
|
# Return a 404 if the package has no screenshots or the image was not found
|
|
unless @screenshot and @screenshot.image.path
|
|
screenshot404
|
|
return
|
|
end
|
|
|
|
# Send the thumbnail (uses X-Sendfile or similar if possible)
|
|
send_file @screenshot.image.path(:large), type: "image/png", disposition: 'inline'
|
|
end
|
|
|
|
# Receives a form with a simple text field 'description' so that users can update
|
|
# the description of their screenshot.
|
|
def update_screenshot_description
|
|
# TODO: Check permissions to do that
|
|
@screenshot = Screenshot.find(params[:id])
|
|
# @screenshot.description = params[:description]
|
|
@screenshot.update params_screenshot_description
|
|
@screenshot.save!
|
|
flash['notice'] = "Description updated."
|
|
redirect_back(fallback_location: package_path(name: @screenshot.package.name))
|
|
end
|
|
|
|
# Receive an anonymous report from a user to have a screenshot removed.
|
|
def report_screenshot
|
|
@screenshot = Screenshot.find(params[:id])
|
|
# if verify_recaptcha
|
|
@screenshot.delete_reason = params[:delete_reason]
|
|
@screenshot.markedfordelete = true
|
|
if @screenshot.valid?
|
|
@screenshot.save!
|
|
flash['notice'] = "Screenshot reported. The moderators will deal with it."
|
|
else
|
|
errors = @screenshot.errors.to_a.join(' and ')
|
|
flash['alert'] = "Sorry. #{errors}"
|
|
end
|
|
# end
|
|
redirect_back(fallback_location: package_path)
|
|
end
|
|
|
|
# Show an HTML partial with reviews of this package from the Ubuntu API
|
|
# def reviews
|
|
# expires_in 1.day, public: true
|
|
# # @reviews = Package.find_by_name!(params[:name]).ubuntu_reviews
|
|
# @reviews = get_ubuntu_reviews params[:name]
|
|
# render '_reviews', layout: false
|
|
# end
|
|
|
|
private
|
|
|
|
# Seamlessly create a user account for the current client.
|
|
# It helps track uploads.
|
|
def create_pseudo_user
|
|
generated_password = Devise.friendly_token.first(8)
|
|
new_user = User.create(
|
|
name: 'Anonymous',
|
|
password: generated_password)
|
|
Log.log "New pseudo user for anonymous upload created: #{new_user}"
|
|
sign_in(new_user)
|
|
end
|
|
|
|
# Send a dummy thumbnail reading "No screenshot available. Sorry."
|
|
def thumbnail404
|
|
send_file Rails.root.join('public/images/dummy/thumbnail404.png'),
|
|
type: "image/png",
|
|
disposition: 'inline',
|
|
status: 404
|
|
end
|
|
|
|
def screenshot404
|
|
send_file Rails.root.join('public/images/dummy/screenshot404.png'),
|
|
type: "image/png",
|
|
disposition: 'inline',
|
|
status: 404
|
|
end
|
|
|
|
# Return packages matching the criteria given by parameters
|
|
def query_packages
|
|
packages = Package.includes(:screenshots).order(created_at: :desc)
|
|
|
|
# text search
|
|
if params[:search].present?
|
|
logger.debug "Searching for #{params[:search]}"
|
|
packages = packages.general_search(params[:search])
|
|
end
|
|
|
|
case params[:show]
|
|
when 'with'
|
|
packages = packages.with_screenshots
|
|
logger.debug 'Limiting packages to those with screenshots'
|
|
when 'without'
|
|
packages = packages.without_screenshots
|
|
logger.debug 'Limiting packages to those without screenshots'
|
|
end
|
|
|
|
return packages
|
|
end
|
|
|
|
# Store a random identifier and the client's IP address in the session
|
|
# for later identification.
|
|
def create_user_token
|
|
session[:token] ||= SecureRandom.hex
|
|
session[:ip] ||= request.remote_ip
|
|
end
|
|
|
|
# Get reviews of this package from the Ubuntu API
|
|
def get_ubuntu_reviews(packagename)
|
|
# Use the URL defined in the configuration to get a JSON string
|
|
url = Rails.configuration.ubuntu_reviews_api_url % packagename
|
|
logger.debug "Loading Ubuntu reviews for package #{packagename} from #{url}"
|
|
|
|
body = open(url).read
|
|
# Turn JSON into a Ruby data structure
|
|
json = JSON.parse(body)
|
|
# Only show english reviews
|
|
# TODO: Support further languages
|
|
json = json.select {|x| x['language']=='en'}
|
|
# Sort by 'usefulness_total' (how many people found this review useful)
|
|
json = json.sort { |x,y| y['usefulness_total'].to_i <=> x['usefulness_total'].to_i}
|
|
return json
|
|
end
|
|
|
|
def params_screenshot_description
|
|
params.require(:screenshot).permit(:description)
|
|
end
|
|
end
|