fixed 解决安全问题访问附件,id改为uuid
This commit is contained in:
parent
0cb38bce4f
commit
d74901cffa
|
@ -94,6 +94,7 @@ class AttachmentsController < ApplicationController
|
||||||
@attachment.author_id = current_user.id
|
@attachment.author_id = current_user.id
|
||||||
@attachment.disk_directory = month_folder
|
@attachment.disk_directory = month_folder
|
||||||
@attachment.cloud_url = remote_path
|
@attachment.cloud_url = remote_path
|
||||||
|
@attachment.uuid = SecureRandom.uuid
|
||||||
@attachment.save!
|
@attachment.save!
|
||||||
else
|
else
|
||||||
logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}"
|
logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}"
|
||||||
|
@ -147,8 +148,9 @@ class AttachmentsController < ApplicationController
|
||||||
if params[:type] == 'history'
|
if params[:type] == 'history'
|
||||||
AttachmentHistory.find params[:id]
|
AttachmentHistory.find params[:id]
|
||||||
else
|
else
|
||||||
Attachment.find params[:id]
|
Attachment.find_by(id: params[:id]) || Attachment.find_by(uuid: params[:id])
|
||||||
end
|
end
|
||||||
|
tip_exception(404, "您访问的页面不存在或已被删除") if @file.blank?
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_file(file_path)
|
def delete_file(file_path)
|
||||||
|
@ -218,7 +220,7 @@ class AttachmentsController < ApplicationController
|
||||||
def attachment_candown
|
def attachment_candown
|
||||||
unless current_user.admin? || current_user.business?
|
unless current_user.admin? || current_user.business?
|
||||||
candown = true
|
candown = true
|
||||||
if @file.container
|
if @file.container && @file.uuid.nil?
|
||||||
if @file.container.is_a?(Issue)
|
if @file.container.is_a?(Issue)
|
||||||
project = @file.container.project
|
project = @file.container.project
|
||||||
candown = project.is_public || (current_user.logged? && project.member?(current_user))
|
candown = project.is_public || (current_user.logged? && project.member?(current_user))
|
||||||
|
|
|
@ -299,7 +299,7 @@ module ApplicationHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def download_url attachment,options={}
|
def download_url attachment,options={}
|
||||||
attachment_path(attachment,options)
|
attachment&.uuid.present? ? attachment_path(attachment.uuid,options) : attachment_path(attachment,options)
|
||||||
end
|
end
|
||||||
|
|
||||||
# 耗时:天、小时、分、秒
|
# 耗时:天、小时、分、秒
|
||||||
|
|
|
@ -1,44 +1,45 @@
|
||||||
# == Schema Information
|
# == Schema Information
|
||||||
#
|
#
|
||||||
# Table name: attachments
|
# Table name: attachments
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
# container_id :integer
|
# container_id :integer
|
||||||
# container_type :string(30)
|
# container_type :string(30)
|
||||||
# filename :string(255) default(""), not null
|
# filename :string(255) default(""), not null
|
||||||
# disk_filename :string(255) default(""), not null
|
# disk_filename :string(255) default(""), not null
|
||||||
# filesize :integer default("0"), not null
|
# filesize :integer default("0"), not null
|
||||||
# content_type :string(255) default("")
|
# content_type :string(255) default("")
|
||||||
# digest :string(60) default(""), not null
|
# digest :string(60) default(""), not null
|
||||||
# downloads :integer default("0"), not null
|
# downloads :integer default("0"), not null
|
||||||
# author_id :integer default("0"), not null
|
# author_id :integer default("0"), not null
|
||||||
# created_on :datetime
|
# created_on :datetime
|
||||||
# description :text(65535)
|
# description :text(65535)
|
||||||
# disk_directory :string(255)
|
# disk_directory :string(255)
|
||||||
# attachtype :integer default("1")
|
# attachtype :integer default("1")
|
||||||
# is_public :integer default("1")
|
# is_public :integer default("1")
|
||||||
# copy_from :integer
|
# copy_from :integer
|
||||||
# quotes :integer default("0")
|
# quotes :integer default("0")
|
||||||
# is_publish :integer default("1")
|
# is_publish :integer default("1")
|
||||||
# publish_time :datetime
|
# publish_time :datetime
|
||||||
# resource_bank_id :integer
|
# resource_bank_id :integer
|
||||||
# unified_setting :boolean default("1")
|
# unified_setting :boolean default("1")
|
||||||
# cloud_url :string(255) default("")
|
# cloud_url :string(255) default("")
|
||||||
# course_second_category_id :integer default("0")
|
# course_second_category_id :integer default("0")
|
||||||
# delay_publish :boolean default("0")
|
# delay_publish :boolean default("0")
|
||||||
# memo_image :boolean default("0")
|
# memo_image :boolean default("0")
|
||||||
# extra_type :integer default("0")
|
# extra_type :integer default("0")
|
||||||
#
|
# uuid :string(255)
|
||||||
# Indexes
|
#
|
||||||
#
|
# Indexes
|
||||||
# index_attachments_on_author_id (author_id)
|
#
|
||||||
# index_attachments_on_container_id_and_container_type (container_id,container_type)
|
# index_attachments_on_author_id (author_id)
|
||||||
# index_attachments_on_course_second_category_id (course_second_category_id)
|
# index_attachments_on_container_id_and_container_type (container_id,container_type)
|
||||||
# index_attachments_on_created_on (created_on)
|
# index_attachments_on_course_second_category_id (course_second_category_id)
|
||||||
# index_attachments_on_is_public (is_public)
|
# index_attachments_on_created_on (created_on)
|
||||||
# index_attachments_on_quotes (quotes)
|
# index_attachments_on_is_public (is_public)
|
||||||
#
|
# index_attachments_on_quotes (quotes)
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,6 +98,11 @@ class Attachment < ApplicationRecord
|
||||||
downloads
|
downloads
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def generate_uuid
|
||||||
|
self.uuid = uuid || SecureRandom.uuid
|
||||||
|
save!
|
||||||
|
end
|
||||||
|
|
||||||
def quotes_count
|
def quotes_count
|
||||||
quotes.nil? ? 0 : quotes
|
quotes.nil? ? 0 : quotes
|
||||||
end
|
end
|
||||||
|
|
|
@ -224,13 +224,23 @@ class Issue < ApplicationRecord
|
||||||
|
|
||||||
# 关附件到功能
|
# 关附件到功能
|
||||||
def associate_attachment_container
|
def associate_attachment_container
|
||||||
|
return if self.project_id == 0
|
||||||
att_ids = []
|
att_ids = []
|
||||||
# 附件的格式为(/api/attachments/ + 附件id)的形式,提取出id进行附件属性关联,做附件访问权限控制
|
# 附件的格式为(/api/attachments/ + 附件id)的形式,提取出id进行附件属性关联,做附件访问权限控制
|
||||||
att_ids += self.description.to_s.scan(/\(\/api\/attachments\/.+\)/).map{|s|s.match(/\d+/)[0]}
|
att_ids += self.description.to_s.scan(/\(\/api\/attachments\/.+\)/).map{|s|s.match(/\d+/)[0]}
|
||||||
att_ids += self.description.to_s.scan(/\/api\/attachments\/.+\"/).map{|s|s.match(/\d+/)[0]}
|
att_ids += self.description.to_s.scan(/\/api\/attachments\/.+\"/).map{|s|s.match(/\d+/)[0]}
|
||||||
att_ids += self.description.to_s.scan(/\/api\/attachments\/\d+/).map{|s|s.match(/\d+/)[0]}
|
att_ids += self.description.to_s.scan(/\/api\/attachments\/\d+/).map{|s|s.match(/\d+/)[0]}
|
||||||
if att_ids.present?
|
if att_ids.present?
|
||||||
Attachment.where(id: att_ids).where("container_type IS NULL OR container_type = 'Issue'").update_all(container_id: self.project_id, container_type: "Project")
|
Attachment.where(id: att_ids).where("container_type IS NULL OR container_type = 'Issue'").update_all(container_id: self.project_id, container_type: 'Project')
|
||||||
|
end
|
||||||
|
|
||||||
|
att_ids2 = []
|
||||||
|
# uuid_regex= /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/
|
||||||
|
# 附件的格式为(/api/attachments/ + uuid)的形式,提取出id进行附件属性关联,做附件访问权限控制
|
||||||
|
att_ids2 += self.description.to_s.scan(/\(\/api\/attachments\/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\)/).map{|s|s.match(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/)[0]}
|
||||||
|
att_ids2 += self.description.to_s.scan(/\/api\/attachments\/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/).map{|s|s.match(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/)[0]}
|
||||||
|
if att_ids2.present?
|
||||||
|
Attachment.where(uuid: att_ids2).where("container_type IS NULL OR container_type = 'Issue'").update_all(container_id: self.project_id, container_type: 'Project')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ class Journal < ApplicationRecord
|
||||||
|
|
||||||
# 关附件到功能
|
# 关附件到功能
|
||||||
def associate_attachment_container
|
def associate_attachment_container
|
||||||
|
return if self.issue&.project_id.to_i == 0
|
||||||
att_ids = []
|
att_ids = []
|
||||||
# 附件的格式为(/api/attachments/ + 附件id)的形式,提取出id进行附件属性关联,做附件访问权限控制
|
# 附件的格式为(/api/attachments/ + 附件id)的形式,提取出id进行附件属性关联,做附件访问权限控制
|
||||||
att_ids += self.notes.to_s.scan(/\(\/api\/attachments\/.+\)/).map{|s|s.match(/\d+/)[0]}
|
att_ids += self.notes.to_s.scan(/\(\/api\/attachments\/.+\)/).map{|s|s.match(/\d+/)[0]}
|
||||||
|
@ -69,6 +70,15 @@ class Journal < ApplicationRecord
|
||||||
if att_ids.present?
|
if att_ids.present?
|
||||||
Attachment.where(id: att_ids).where("container_type IS NULL OR container_type = 'Journal'").update_all(container_id: self.issue.project_id, container_type: "Project")
|
Attachment.where(id: att_ids).where("container_type IS NULL OR container_type = 'Journal'").update_all(container_id: self.issue.project_id, container_type: "Project")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
att_ids2 = []
|
||||||
|
# uuid_regex= /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/
|
||||||
|
# 附件的格式为(/api/attachments/ + uuid)的形式,提取出id进行附件属性关联,做附件访问权限控制
|
||||||
|
att_ids2 += self.notes.to_s.scan(/\(\/api\/attachments\/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\)/).map{|s|s.match(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/)[0]}
|
||||||
|
att_ids2 += self.notes.to_s.scan(/\/api\/attachments\/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/).map{|s|s.match(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/)[0]}
|
||||||
|
if att_ids2.present?
|
||||||
|
Attachment.where(uuid: att_ids).where("container_type IS NULL OR container_type = 'Journal'").update_all(container_id: self.issue.project_id, container_type: "Project")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def operate_content
|
def operate_content
|
||||||
|
|
|
@ -31,7 +31,7 @@ module Api::V1::Issues::Concerns::Checkable
|
||||||
def check_attachments (attachment_ids)
|
def check_attachments (attachment_ids)
|
||||||
raise ApplicationService::Error, "请输入正确的附件ID数组!" unless attachment_ids.is_a?(Array)
|
raise ApplicationService::Error, "请输入正确的附件ID数组!" unless attachment_ids.is_a?(Array)
|
||||||
attachment_ids.each do |aid|
|
attachment_ids.each do |aid|
|
||||||
raise ApplicationService::Error, "请输入正确的附件ID!" unless Attachment.exists?(id: aid)
|
raise ApplicationService::Error, "请输入正确的附件ID!" unless Attachment.exists?(id: aid) || Attachment.exists?(uuid: aid)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ module Api::V1::Issues::Concerns::Loadable
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_attachments(attachment_ids)
|
def load_attachments(attachment_ids)
|
||||||
@attachments = Attachment.where(id: attachment_ids)
|
@attachments = Attachment.where(id: attachment_ids).or(Attachment.where(uuid: attachment_ids))
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_atme_receivers(receivers_login)
|
def load_atme_receivers(receivers_login)
|
||||||
|
|
|
@ -1,2 +1,7 @@
|
||||||
json.id @attachment.id
|
json.id @attachment.uuid
|
||||||
json.filesize @attachment.filesize
|
json.title @attachment.title
|
||||||
|
json.filesize number_to_human_size(@attachment.filesize)
|
||||||
|
json.is_pdf @attachment.is_pdf?
|
||||||
|
json.url Rails.application.config_for(:configuration)['platform_url'] + (@attachment.is_pdf? ? download_url(@attachment,disposition:"inline") : download_url(@attachment)).to_s
|
||||||
|
json.created_on @attachment.created_on.strftime("%Y-%m-%d %H:%M")
|
||||||
|
json.content_type @attachment.content_type
|
||||||
|
|
Loading…
Reference in New Issue