mirror of
https://github.com/discourse/discourse.git
synced 2025-05-22 16:11:08 +08:00
PERF: remove "fog" dependency
This commit is contained in:
111
lib/s3_helper.rb
111
lib/s3_helper.rb
@ -1,50 +1,76 @@
|
||||
require "fog"
|
||||
require "aws-sdk"
|
||||
|
||||
class S3Helper
|
||||
|
||||
def initialize(s3_bucket, tombstone_prefix=nil, fog=nil)
|
||||
def initialize(s3_bucket, tombstone_prefix=nil)
|
||||
raise Discourse::InvalidParameters.new("s3_bucket") if s3_bucket.blank?
|
||||
|
||||
@s3_bucket = s3_bucket
|
||||
@tombstone_prefix = tombstone_prefix
|
||||
|
||||
check_missing_site_settings
|
||||
|
||||
@fog = fog || Fog::Storage.new(s3_options)
|
||||
end
|
||||
|
||||
def upload(file, unique_filename, options={})
|
||||
args = {
|
||||
body: file,
|
||||
key: unique_filename,
|
||||
public: false,
|
||||
}
|
||||
|
||||
args.merge!(options)
|
||||
|
||||
directory = get_or_create_directory(@s3_bucket)
|
||||
directory.files.create(args)
|
||||
obj = s3_bucket.object(unique_filename)
|
||||
obj.upload_file(file, options)
|
||||
end
|
||||
|
||||
def remove(unique_filename, copy_to_tombstone=false)
|
||||
bucket = s3_bucket
|
||||
|
||||
# copy the file in tombstone
|
||||
if copy_to_tombstone && @tombstone_prefix.present?
|
||||
@fog.copy_object(unique_filename, @s3_bucket, @tombstone_prefix + unique_filename, @s3_bucket)
|
||||
bucket.object(@tombstone_prefix + unique_filename).copy_from(copy_source: "#{@s3_bucket}/#{unique_filename}")
|
||||
end
|
||||
# delete the file
|
||||
@fog.delete_object(@s3_bucket, unique_filename)
|
||||
rescue Excon::Errors::NotFound
|
||||
# if the file cannot be found, don't raise an error
|
||||
bucket.object(unique_filename).delete
|
||||
rescue Aws::S3::Errors::NoSuchKey
|
||||
end
|
||||
|
||||
def update_tombstone_lifecycle(grace_period)
|
||||
|
||||
return if @tombstone_prefix.blank?
|
||||
# cf. http://docs.aws.amazon.com/AmazonS3/latest/dev/object-lifecycle-mgmt.html
|
||||
@fog.put_bucket_lifecycle(@s3_bucket, lifecycle(grace_period))
|
||||
s3_resource.client.put_bucket_lifecycle({
|
||||
bucket: @s3_bucket,
|
||||
lifecycle_configuration: {
|
||||
rules: [
|
||||
{
|
||||
id: 'purge-tombstone',
|
||||
status: 'Enabled',
|
||||
expiration: {
|
||||
days: grace_period
|
||||
},
|
||||
prefix: @tombstone_prefix
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def s3_resource
|
||||
opts = {}
|
||||
|
||||
opts = {
|
||||
access_key_id: SiteSetting.s3_access_key_id,
|
||||
secret_access_key: SiteSetting.s3_secret_access_key
|
||||
} unless SiteSetting.s3_use_iam_profile
|
||||
|
||||
opts[:region] = SiteSetting.s3_region unless SiteSetting.s3_region.blank?
|
||||
|
||||
Aws::S3::Resource.new(opts)
|
||||
end
|
||||
|
||||
def s3_bucket
|
||||
bucket = s3_resource.bucket(@s3_bucket)
|
||||
bucket.create unless bucket.exists?
|
||||
bucket
|
||||
end
|
||||
|
||||
|
||||
def check_missing_site_settings
|
||||
unless SiteSetting.s3_use_iam_profile
|
||||
raise Discourse::SiteSettingMissing.new("s3_access_key_id") if SiteSetting.s3_access_key_id.blank?
|
||||
@ -52,51 +78,4 @@ class S3Helper
|
||||
end
|
||||
end
|
||||
|
||||
def s3_options
|
||||
options = { provider: 'AWS', scheme: SiteSetting.scheme }
|
||||
|
||||
# cf. https://github.com/fog/fog/issues/2381
|
||||
options[:path_style] = dns_compatible?(@s3_bucket, SiteSetting.use_https?)
|
||||
|
||||
options[:region] = SiteSetting.s3_region unless SiteSetting.s3_region.blank?
|
||||
|
||||
if SiteSetting.s3_use_iam_profile
|
||||
options.merge!(use_iam_profile: true)
|
||||
else
|
||||
options.merge!(aws_access_key_id: SiteSetting.s3_access_key_id,
|
||||
aws_secret_access_key: SiteSetting.s3_secret_access_key)
|
||||
end
|
||||
|
||||
options
|
||||
end
|
||||
|
||||
def get_or_create_directory(bucket)
|
||||
directory = @fog.directories.get(bucket)
|
||||
directory = @fog.directories.create(key: bucket) unless directory
|
||||
directory
|
||||
end
|
||||
|
||||
def lifecycle(grace_period)
|
||||
{
|
||||
"Rules" => [{
|
||||
"Prefix" => @tombstone_prefix,
|
||||
"Enabled" => true,
|
||||
"Expiration" => { "Days" => grace_period }
|
||||
}]
|
||||
}
|
||||
end
|
||||
|
||||
# cf. https://github.com/aws/aws-sdk-core-ruby/blob/master/aws-sdk-core/lib/aws-sdk-core/plugins/s3_bucket_dns.rb#L65-L80
|
||||
def dns_compatible?(bucket_name, ssl)
|
||||
return false unless valid_subdomain?(bucket_name)
|
||||
bucket_name.match(/\./) && ssl ? false : true
|
||||
end
|
||||
|
||||
def valid_subdomain?(bucket_name)
|
||||
bucket_name.size < 64 &&
|
||||
bucket_name =~ /^[a-z0-9][a-z0-9.-]+[a-z0-9]$/ &&
|
||||
bucket_name !~ /(\d+\.){3}\d+/ &&
|
||||
bucket_name !~ /[.-]{2}/
|
||||
end
|
||||
|
||||
end
|
||||
|
Reference in New Issue
Block a user