active_storage_db 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 23bbb0b9bf0759169020c1da8e4a8d5028938ffdb1b13dc4a356783da06eb868
4
- data.tar.gz: 1e1e1146a363bba15efe440cd82fbc4926763596746995f8696c24ca9cb9789c
3
+ metadata.gz: 33872893aefc8f1086a8c422819990e10d1d46d2b97bd87d67662fd153536243
4
+ data.tar.gz: 0e662cd62a06ec353c9e02706c1c553500edafa146e4149d21fa57626d129d5a
5
5
  SHA512:
6
- metadata.gz: cc1229568804d8a6c1a0912f8ddcf59895d12374a57b460a6f29c8bce1aac7216c936b6b8c255ea41563f39b22c748e34645bac787da24886d9c02bcd367adb3
7
- data.tar.gz: b85e8f1b41dfc2e01cfb566efd561a44606959cd1cb6b3a9cf718e4618b396949aad3fa87f8037ba61eda0789425bf9b4cf1031805d370c4702d2c973a5dfe5b
6
+ metadata.gz: a418655f7275cc54264b25733712cbe813eeede79eb7d08833c2e333427d7a9c1cb44f1c46b3a338cf20407abf0d7d9b59e2dfcdec0f1467b77f47ca85b7357e
7
+ data.tar.gz: ac8d6c3c8fc9c44177d474c709f67ff5a46a8c1835c15e9f753773ac846851e23bd13ef2e8e0c3fd13185ea0d8f528f31aac8ae48275a46288bde22a6ad04dee
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # Active Storage DB
2
2
 
3
3
  [![gem version](https://badge.fury.io/rb/active_storage_db.svg)](https://badge.fury.io/rb/active_storage_db)
4
+ [![gem downloads](https://badgen.net/rubygems/dt/active_storage_db)](https://rubygems.org/gems/active_storage_db)
5
+ [![maintainability](https://api.codeclimate.com/v1/badges/92e1e703c308744a0f66/maintainability)](https://codeclimate.com/github/blocknotes/active_storage_db/maintainability)
6
+
4
7
  [![linters](https://github.com/blocknotes/active_storage_db/actions/workflows/linters.yml/badge.svg)](https://github.com/blocknotes/active_storage_db/actions/workflows/linters.yml)
5
8
  [![specs Postgres](https://github.com/blocknotes/active_storage_db/actions/workflows/specs_postgres_70.yml/badge.svg)](https://github.com/blocknotes/active_storage_db/actions/workflows/specs_postgres_70.yml)
6
9
  [![Specs MySQL](https://github.com/blocknotes/active_storage_db/actions/workflows/specs_mysql_70.yml/badge.svg)](https://github.com/blocknotes/active_storage_db/actions/workflows/specs_mysql_70.yml)
@@ -8,34 +8,41 @@ module ActiveStorageDB
8
8
  if (key = decode_verified_key)
9
9
  serve_file(key[:key], content_type: key[:content_type], disposition: key[:disposition])
10
10
  else
11
- head :not_found
11
+ head(:not_found)
12
12
  end
13
13
  rescue ActiveStorage::FileNotFoundError
14
- head :not_found
14
+ head(:not_found)
15
15
  end
16
16
 
17
17
  def update
18
18
  if (token = decode_verified_token)
19
- if acceptable_content?(token)
20
- db_service.upload(token[:key], request.body, checksum: token[:checksum])
21
- else
22
- head :unprocessable_entity
23
- end
19
+ file_uploaded = upload_file(token, body: request.body)
20
+ head(file_uploaded ? :no_content : :unprocessable_entity)
24
21
  else
25
- head :not_found
22
+ head(:not_found)
26
23
  end
27
24
  rescue ActiveStorage::IntegrityError
28
- head :unprocessable_entity
25
+ head(:unprocessable_entity)
29
26
  end
30
27
 
31
28
  private
32
29
 
30
+ def acceptable_content?(token)
31
+ token[:content_type] == request.content_mime_type && token[:content_length] == request.content_length
32
+ end
33
+
33
34
  def db_service
34
35
  ActiveStorage::Blob.service
35
36
  end
36
37
 
37
38
  def decode_verified_key
38
- ActiveStorage.verifier.verified(params[:encoded_key], purpose: :blob_key)
39
+ key = ActiveStorage.verifier.verified(params[:encoded_key], purpose: :blob_key)
40
+ key&.deep_symbolize_keys
41
+ end
42
+
43
+ def decode_verified_token
44
+ token = ActiveStorage.verifier.verified(params[:encoded_token], purpose: :blob_token)
45
+ token&.deep_symbolize_keys
39
46
  end
40
47
 
41
48
  def serve_file(key, content_type:, disposition:)
@@ -43,15 +50,14 @@ module ActiveStorageDB
43
50
  type: content_type || DEFAULT_SEND_FILE_TYPE,
44
51
  disposition: disposition || DEFAULT_SEND_FILE_DISPOSITION
45
52
  }
46
- send_data db_service.download(key), options
53
+ send_data(db_service.download(key), options)
47
54
  end
48
55
 
49
- def decode_verified_token
50
- ActiveStorage.verifier.verified(params[:encoded_token], purpose: :blob_token)
51
- end
56
+ def upload_file(token, body:)
57
+ return false unless acceptable_content?(token)
52
58
 
53
- def acceptable_content?(token)
54
- token[:content_type] == request.content_mime_type && token[:content_length] == request.content_length
59
+ db_service.upload(token[:key], request.body, checksum: token[:checksum])
60
+ true
55
61
  end
56
62
  end
57
63
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveStorageDB
4
+ class ApplicationRecord < ActiveRecord::Base
5
+ self.abstract_class = true
6
+ end
7
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveStorageDB
4
- class File < ActiveRecord::Base
4
+ class File < ApplicationRecord
5
5
  validates :ref,
6
6
  presence: true,
7
7
  allow_blank: false,
@@ -2,12 +2,25 @@
2
2
 
3
3
  class CreateActiveStorageDBFiles < ActiveRecord::Migration[6.0]
4
4
  def change
5
- create_table :active_storage_db_files do |t|
5
+ create_table :active_storage_db_files, id: primary_key_type do |t|
6
6
  t.string :ref, null: false
7
7
  t.binary :data, null: false
8
- t.datetime :created_at, null: false
8
+
9
+ if connection.supports_datetime_with_precision?
10
+ t.datetime :created_at, precision: 6, null: false
11
+ else
12
+ t.datetime :created_at, null: false
13
+ end
9
14
 
10
15
  t.index [:ref], unique: true
11
16
  end
12
17
  end
18
+
19
+ private
20
+
21
+ def primary_key_type
22
+ config = Rails.configuration.generators
23
+ primary_key_type = config.options[config.orm][:primary_key_type]
24
+ primary_key_type || :primary_key
25
+ end
13
26
  end
@@ -36,18 +36,14 @@ module ActiveStorage
36
36
  end
37
37
  else
38
38
  instrument :download, key: key do
39
- record = ::ActiveStorageDB::File.find_by(ref: key)
40
- raise(ActiveStorage::FileNotFoundError) unless record
41
-
42
- record.data
39
+ retrieve_file(key)
43
40
  end
44
41
  end
45
42
  end
46
43
 
47
44
  def download_chunk(key, range)
48
45
  instrument :download_chunk, key: key, range: range do
49
- chunk_select = "SUBSTRING(data FROM #{range.begin + 1} FOR #{range.size}) AS chunk"
50
- record = ::ActiveStorageDB::File.select(chunk_select).find_by(ref: key)
46
+ record = object_for(key, fields: "SUBSTRING(data FROM #{range.begin + 1} FOR #{range.size}) AS chunk")
51
47
  raise(ActiveStorage::FileNotFoundError) unless record
52
48
 
53
49
  record.chunk
@@ -63,7 +59,7 @@ module ActiveStorage
63
59
 
64
60
  def delete_prefixed(prefix)
65
61
  instrument :delete_prefixed, prefix: prefix do
66
- ::ActiveStorageDB::File.where('ref LIKE ?', "#{prefix}%").destroy_all
62
+ ::ActiveStorageDB::File.where('ref LIKE ?', "#{ApplicationRecord.sanitize_sql_like(prefix)}%").destroy_all
67
63
  end
68
64
  end
69
65
 
@@ -127,17 +123,26 @@ module ActiveStorage
127
123
  end
128
124
 
129
125
  def ensure_integrity_of(key, checksum)
130
- file = ::ActiveStorageDB::File.find_by(ref: key)
131
- return if Digest::MD5.base64digest(file.data) == checksum
126
+ return if Digest::MD5.base64digest(object_for(key).data) == checksum
132
127
 
133
128
  delete(key)
134
129
  raise ActiveStorage::IntegrityError
135
130
  end
136
131
 
132
+ def retrieve_file(key)
133
+ file = object_for(key)
134
+ raise(ActiveStorage::FileNotFoundError) unless file
135
+
136
+ file.data
137
+ end
138
+
139
+ def object_for(key, fields: nil)
140
+ as_file = fields ? ::ActiveStorageDB::File.select(*fields) : ::ActiveStorageDB::File
141
+ as_file.find_by(ref: key)
142
+ end
143
+
137
144
  def stream(key)
138
- size =
139
- ::ActiveStorageDB::File.select('OCTET_LENGTH(data) AS size').find_by(ref: key)&.size ||
140
- raise(ActiveStorage::FileNotFoundError)
145
+ size = object_for(key, fields: 'OCTET_LENGTH(data) AS size')&.size || raise(ActiveStorage::FileNotFoundError)
141
146
  (size / @chunk_size.to_f).ceil.times.each do |i|
142
147
  range = (i * @chunk_size..((i + 1) * @chunk_size) - 1)
143
148
  yield download_chunk(key, range)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveStorageDB
4
- VERSION = '1.1.0'
4
+ VERSION = '1.1.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_storage_db
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattia Roccoberton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-04 00:00:00.000000000 Z
11
+ date: 2022-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activestorage
@@ -77,6 +77,7 @@ files:
77
77
  - README.md
78
78
  - Rakefile
79
79
  - app/controllers/active_storage_db/files_controller.rb
80
+ - app/models/active_storage_db/application_record.rb
80
81
  - app/models/active_storage_db/file.rb
81
82
  - config/initializers/inflections.rb
82
83
  - config/routes.rb