Class: BackupRestore::S3BackupStore

Inherits:
BackupStore show all
Defined in:
lib/backup_restore/s3_backup_store.rb

Constant Summary

Constants inherited from BackupStore

BackupStore::BackupFileExists, BackupStore::StorageError

Instance Method Summary collapse

Methods inherited from BackupStore

create, #delete_old, #files, #latest_file, #reset_cache, #stats

Constructor Details

#initialize(opts = {}) ⇒ S3BackupStore

Returns a new instance of S3BackupStore.



13
14
15
16
# File 'lib/backup_restore/s3_backup_store.rb', line 13

def initialize(opts = {})
  @s3_options = S3Helper.s3_options(SiteSetting)
  @s3_options.merge!(opts[:s3_options]) if opts[:s3_options]
end

Instance Method Details

#create_multipart(file_name, content_type, metadata: {}) ⇒ Object

Raises:



102
103
104
105
106
107
# File 'lib/backup_restore/s3_backup_store.rb', line 102

def create_multipart(file_name, content_type, metadata: {})
  obj = object_from_path(file_name)
  raise BackupFileExists.new if obj.exists?
  key = temporary_upload_path(file_name)
  s3_helper.create_multipart(key, content_type, metadata: )
end

#delete_file(filename) ⇒ Object



31
32
33
34
35
36
37
38
# File 'lib/backup_restore/s3_backup_store.rb', line 31

def delete_file(filename)
  obj = s3_helper.object(filename)

  if obj.exists?
    obj.delete
    reset_cache
  end
end

#download_file(filename, destination_path, failure_message = nil) ⇒ Object



40
41
42
# File 'lib/backup_restore/s3_backup_store.rb', line 40

def download_file(filename, destination_path, failure_message = nil)
  s3_helper.download_file(filename, destination_path, failure_message)
end

#file(filename, include_download_source: false) ⇒ Object



26
27
28
29
# File 'lib/backup_restore/s3_backup_store.rb', line 26

def file(filename, include_download_source: false)
  obj = s3_helper.object(filename)
  create_file_from_object(obj, include_download_source) if obj.exists?
end

#generate_upload_url(filename) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/backup_restore/s3_backup_store.rb', line 52

def generate_upload_url(filename)
  obj = s3_helper.object(filename)
  raise BackupFileExists.new if obj.exists?

  # TODO (martin) We can remove this at a later date when we move this
  # ensure CORS for backups and direct uploads to a post-site-setting
  # change event, so the rake task doesn't have to be run manually.
  @s3_helper.ensure_cors!([S3CorsRulesets::BACKUP_DIRECT_UPLOAD])

  presigned_url(obj, :put, UPLOAD_URL_EXPIRES_AFTER_SECONDS)
rescue Aws::Errors::ServiceError => e
  Rails.logger.warn(
    "Failed to generate upload URL for S3: #{e.message.presence || e.class.name}",
  )
  raise StorageError.new(e.message.presence || e.class.name)
end

#move_existing_stored_upload(existing_external_upload_key:, original_filename: nil, content_type: nil) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/backup_restore/s3_backup_store.rb', line 109

def move_existing_stored_upload(
  existing_external_upload_key:,
  original_filename: nil,
  content_type: nil
)
  s3_helper.copy(
    existing_external_upload_key,
    File.join(s3_helper.s3_bucket_folder_path, original_filename),
    options: {
      acl: SiteSetting.s3_use_acls ? "private" : nil,
      apply_metadata_to_destination: true,
    },
  )
  s3_helper.delete_object(existing_external_upload_key)
end

#object_from_path(path) ⇒ Object



125
126
127
# File 'lib/backup_restore/s3_backup_store.rb', line 125

def object_from_path(path)
  s3_helper.object(path)
end

#remote?Boolean

Returns:

  • (Boolean)


22
23
24
# File 'lib/backup_restore/s3_backup_store.rb', line 22

def remote?
  true
end

#s3_helperObject



18
19
20
# File 'lib/backup_restore/s3_backup_store.rb', line 18

def s3_helper
  @s3_helper ||= S3Helper.new(s3_bucket_name_with_prefix, "", @s3_options.clone)
end

#signed_url_for_temporary_upload(file_name, expires_in: S3Helper::UPLOAD_URL_EXPIRES_AFTER_SECONDS, metadata: {}) ⇒ Object

Raises:



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/backup_restore/s3_backup_store.rb', line 69

def signed_url_for_temporary_upload(
  file_name,
  expires_in: S3Helper::UPLOAD_URL_EXPIRES_AFTER_SECONDS,
  metadata: {}
)
  obj = object_from_path(file_name)
  raise BackupFileExists.new if obj.exists?
  key = temporary_upload_path(file_name)
  s3_helper.presigned_url(
    key,
    method: :put_object,
    expires_in: expires_in,
    opts: {
      metadata: ,
      acl: SiteSetting.s3_use_acls ? "private" : nil,
    },
  )
end

#temporary_folder_prefixObject



92
93
94
95
96
97
98
99
100
# File 'lib/backup_restore/s3_backup_store.rb', line 92

def temporary_folder_prefix
  folder_prefix = s3_helper.s3_bucket_folder_path.nil? ? "" : s3_helper.s3_bucket_folder_path

  if Rails.env.test?
    folder_prefix = File.join(folder_prefix, "test_#{ENV["TEST_ENV_NUMBER"].presence || "0"}")
  end

  folder_prefix
end

#temporary_upload_path(file_name) ⇒ Object



88
89
90
# File 'lib/backup_restore/s3_backup_store.rb', line 88

def temporary_upload_path(file_name)
  FileStore::BaseStore.temporary_upload_path(file_name, folder_prefix: temporary_folder_prefix)
end

#upload_file(filename, source_path, content_type) ⇒ Object

Raises:



44
45
46
47
48
49
50
# File 'lib/backup_restore/s3_backup_store.rb', line 44

def upload_file(filename, source_path, content_type)
  obj = s3_helper.object(filename)
  raise BackupFileExists.new if obj.exists?

  obj.upload_file(source_path, content_type: content_type)
  reset_cache
end