active_storage_db 1.1.0 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
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