GithubHelp home page GithubHelp logo

mul53 / activestorage-ipfs Goto Github PK

View Code? Open in Web Editor NEW
19.0 19.0 5.0 36 KB

This gem extends the ActiveStorage::Service with an implementation for IPFS

License: MIT License

Ruby 98.90% Shell 1.10%

activestorage-ipfs's People

Contributors

andrew avatar dependabot[bot] avatar mul53 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

activestorage-ipfs's Issues

Is development active?

Hello, we are planning a project that would likely depend on this gem, and we would like to know if the developer team is in a position to continue the development or at least accept pull requests?

What is the situation on your side?

Thanks.

Add mention to readme about CORS config for direct uploads

When using the direct upload feature pointed at localhost, you get a CORS error from IPFS, can you add a note to enable CORS on your node in the readme? The commands to enable it are:

ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["*"]'
ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '["PUT", "GET", "POST"]'

Errors when trying to upload the same file twice

When uploading the same file twice, rails throws a ActiveRecord::RecordNotUnique error, I guess because the CID is the same and there's a uniqueness constraint on the key in the blob store table.

Perhaps it needs to attempt to find an existing record and use that in this case?

Started POST "/rails/active_storage/direct_uploads" for 127.0.0.1 at 2020-06-18 12:21:26 +0100
Processing by ActiveStorage::DirectUploadsController#create as JSON
  Parameters: {"blob"=>{"key"=>"QmSyQ4e1KfMSdwP8A3Ks5HZMmVBXDuDXPqCd3kwwtqvVGp", "filename"=>"Photo on 25-05-2018 at 15.27.jpg", "content_type"=>"image/jpeg", "byte_size"=>135488, "checksum"=>"OAjxf4CriGSVkuIJTetm1g=="}, "direct_upload"=>{"blob"=>{"key"=>"QmSyQ4e1KfMSdwP8A3Ks5HZMmVBXDuDXPqCd3kwwtqvVGp", "filename"=>"Photo on 25-05-2018 at 15.27.jpg", "content_type"=>"image/jpeg", "byte_size"=>135488, "checksum"=>"OAjxf4CriGSVkuIJTetm1g=="}}}
   (0.1ms)  begin transaction
  ActiveStorage::Blob Create (0.9ms)  INSERT INTO "active_storage_blobs" ("key", "filename", "content_type", "byte_size", "checksum", "created_at") VALUES (?, ?, ?, ?, ?, ?)  [["key", "QmSyQ4e1KfMSdwP8A3Ks5HZMmVBXDuDXPqCd3kwwtqvVGp"], ["filename", "Photo on 25-05-2018 at 15.27.jpg"], ["content_type", "image/jpeg"], ["byte_size", 135488], ["checksum", "OAjxf4CriGSVkuIJTetm1g=="], ["created_at", "2020-06-18 11:21:26.608964"]]
   (0.1ms)  rollback transaction
Completed 500 Internal Server Error in 8ms (ActiveRecord: 1.1ms | Allocations: 5346)


  
ActiveRecord::RecordNotUnique (SQLite3::ConstraintException: UNIQUE constraint failed: active_storage_blobs.key):
  
sqlite3 (1.4.2) lib/sqlite3/statement.rb:108:in `step'
sqlite3 (1.4.2) lib/sqlite3/statement.rb:108:in `block in each'
sqlite3 (1.4.2) lib/sqlite3/statement.rb:107:in `loop'
sqlite3 (1.4.2) lib/sqlite3/statement.rb:107:in `each'
activerecord (6.0.3.2) lib/active_record/connection_adapters/sqlite3/database_statements.rb:49:in `to_a'
activerecord (6.0.3.2) lib/active_record/connection_adapters/sqlite3/database_statements.rb:49:in `block (2 levels) in exec_query'
activesupport (6.0.3.2) lib/active_support/dependencies/interlock.rb:48:in `block in permit_concurrent_loads'
activesupport (6.0.3.2) lib/active_support/concurrency/share_lock.rb:187:in `yield_shares'
activesupport (6.0.3.2) lib/active_support/dependencies/interlock.rb:47:in `permit_concurrent_loads'
activerecord (6.0.3.2) lib/active_record/connection_adapters/sqlite3/database_statements.rb:40:in `block in exec_query'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract_adapter.rb:722:in `block (2 levels) in log'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:26:in `block (2 levels) in synchronize'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract_adapter.rb:721:in `block in log'
activesupport (6.0.3.2) lib/active_support/notifications/instrumenter.rb:24:in `instrument'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract_adapter.rb:712:in `log'
activerecord (6.0.3.2) lib/active_record/connection_adapters/sqlite3/database_statements.rb:39:in `exec_query'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract/database_statements.rb:135:in `exec_insert'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract/database_statements.rb:166:in `insert'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract/query_cache.rb:22:in `insert'
activerecord (6.0.3.2) lib/active_record/persistence.rb:375:in `_insert_record'
activerecord (6.0.3.2) lib/active_record/persistence.rb:932:in `_create_record'
activerecord (6.0.3.2) lib/active_record/counter_cache.rb:166:in `_create_record'
activerecord (6.0.3.2) lib/active_record/locking/optimistic.rb:70:in `_create_record'
activerecord (6.0.3.2) lib/active_record/attribute_methods/dirty.rb:211:in `_create_record'
activerecord (6.0.3.2) lib/active_record/callbacks.rb:331:in `block in _create_record'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:135:in `run_callbacks'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:825:in `_run_create_callbacks'
activerecord (6.0.3.2) lib/active_record/callbacks.rb:331:in `_create_record'
activerecord (6.0.3.2) lib/active_record/timestamp.rb:110:in `_create_record'
activerecord (6.0.3.2) lib/active_record/persistence.rb:905:in `create_or_update'
activerecord (6.0.3.2) lib/active_record/callbacks.rb:327:in `block in create_or_update'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:135:in `run_callbacks'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:825:in `_run_save_callbacks'
activerecord (6.0.3.2) lib/active_record/callbacks.rb:327:in `create_or_update'
activerecord (6.0.3.2) lib/active_record/timestamp.rb:128:in `create_or_update'
activerecord (6.0.3.2) lib/active_record/persistence.rb:503:in `save!'
activerecord (6.0.3.2) lib/active_record/validations.rb:53:in `save!'
activerecord (6.0.3.2) lib/active_record/transactions.rb:318:in `block in save!'
activerecord (6.0.3.2) lib/active_record/transactions.rb:375:in `block in with_transaction_returning_status'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract/database_statements.rb:280:in `block in transaction'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract/transaction.rb:280:in `block in within_new_transaction'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:26:in `block (2 levels) in synchronize'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract/transaction.rb:278:in `within_new_transaction'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract/database_statements.rb:280:in `transaction'
activerecord (6.0.3.2) lib/active_record/transactions.rb:212:in `transaction'
activerecord (6.0.3.2) lib/active_record/transactions.rb:366:in `with_transaction_returning_status'
activerecord (6.0.3.2) lib/active_record/transactions.rb:318:in `save!'
activerecord (6.0.3.2) lib/active_record/suppressor.rb:48:in `save!'
activerecord (6.0.3.2) lib/active_record/persistence.rb:55:in `create!'
activestorage-ipfs (a4b1b89a9330) lib/active_storage/service/ipfs_service.rb:13:in `create_before_direct_upload!'
activestorage (6.0.3.2) app/controllers/active_storage/direct_uploads_controller.rb:8:in `create'
actionpack (6.0.3.2) lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
actionpack (6.0.3.2) lib/abstract_controller/base.rb:195:in `process_action'
actionpack (6.0.3.2) lib/action_controller/metal/rendering.rb:30:in `process_action'
actionpack (6.0.3.2) lib/abstract_controller/callbacks.rb:42:in `block in process_action'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:135:in `run_callbacks'
actionpack (6.0.3.2) lib/abstract_controller/callbacks.rb:41:in `process_action'
actionpack (6.0.3.2) lib/action_controller/metal/rescue.rb:22:in `process_action'
actionpack (6.0.3.2) lib/action_controller/metal/instrumentation.rb:33:in `block in process_action'
activesupport (6.0.3.2) lib/active_support/notifications.rb:180:in `block in instrument'
activesupport (6.0.3.2) lib/active_support/notifications/instrumenter.rb:24:in `instrument'
activesupport (6.0.3.2) lib/active_support/notifications.rb:180:in `instrument'
actionpack (6.0.3.2) lib/action_controller/metal/instrumentation.rb:32:in `process_action'
actionpack (6.0.3.2) lib/action_controller/metal/params_wrapper.rb:245:in `process_action'
activerecord (6.0.3.2) lib/active_record/railties/controller_runtime.rb:27:in `process_action'
actionpack (6.0.3.2) lib/abstract_controller/base.rb:136:in `process'
actionview (6.0.3.2) lib/action_view/rendering.rb:39:in `process'
actionpack (6.0.3.2) lib/action_controller/metal.rb:190:in `dispatch'
actionpack (6.0.3.2) lib/action_controller/metal.rb:254:in `dispatch'
actionpack (6.0.3.2) lib/action_dispatch/routing/route_set.rb:50:in `dispatch'
actionpack (6.0.3.2) lib/action_dispatch/routing/route_set.rb:33:in `serve'
actionpack (6.0.3.2) lib/action_dispatch/journey/router.rb:49:in `block in serve'
actionpack (6.0.3.2) lib/action_dispatch/journey/router.rb:32:in `each'
actionpack (6.0.3.2) lib/action_dispatch/journey/router.rb:32:in `serve'
actionpack (6.0.3.2) lib/action_dispatch/routing/route_set.rb:834:in `call'
rack (2.2.3) lib/rack/tempfile_reaper.rb:15:in `call'
rack (2.2.3) lib/rack/etag.rb:27:in `call'
rack (2.2.3) lib/rack/conditional_get.rb:40:in `call'
rack (2.2.3) lib/rack/head.rb:12:in `call'
actionpack (6.0.3.2) lib/action_dispatch/http/content_security_policy.rb:18:in `call'
rack (2.2.3) lib/rack/session/abstract/id.rb:266:in `context'
rack (2.2.3) lib/rack/session/abstract/id.rb:260:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/cookies.rb:648:in `call'
activerecord (6.0.3.2) lib/active_record/migration.rb:567:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/callbacks.rb:27:in `block in call'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:101:in `run_callbacks'
actionpack (6.0.3.2) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/actionable_exceptions.rb:17:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/debug_exceptions.rb:32:in `call'
web-console (4.0.3) lib/web_console/middleware.rb:132:in `call_app'
web-console (4.0.3) lib/web_console/middleware.rb:28:in `block in call'
web-console (4.0.3) lib/web_console/middleware.rb:17:in `catch'
web-console (4.0.3) lib/web_console/middleware.rb:17:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
railties (6.0.3.2) lib/rails/rack/logger.rb:37:in `call_app'
railties (6.0.3.2) lib/rails/rack/logger.rb:26:in `block in call'
activesupport (6.0.3.2) lib/active_support/tagged_logging.rb:80:in `block in tagged'
activesupport (6.0.3.2) lib/active_support/tagged_logging.rb:28:in `tagged'
activesupport (6.0.3.2) lib/active_support/tagged_logging.rb:80:in `tagged'
railties (6.0.3.2) lib/rails/rack/logger.rb:26:in `call'
sprockets-rails (3.2.1) lib/sprockets/rails/quiet_assets.rb:13:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/request_id.rb:27:in `call'
rack (2.2.3) lib/rack/method_override.rb:24:in `call'
rack (2.2.3) lib/rack/runtime.rb:22:in `call'
activesupport (6.0.3.2) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/static.rb:126:in `call'
rack (2.2.3) lib/rack/sendfile.rb:110:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/host_authorization.rb:82:in `call'
webpacker (4.2.2) lib/webpacker/dev_server_proxy.rb:23:in `perform_request'
rack-proxy (0.6.5) lib/rack/proxy.rb:57:in `call'
railties (6.0.3.2) lib/rails/engine.rb:527:in `call'
puma (4.3.5) lib/puma/configuration.rb:228:in `call'
puma (4.3.5) lib/puma/server.rb:713:in `handle_request'
puma (4.3.5) lib/puma/server.rb:472:in `process_client'
puma (4.3.5) lib/puma/server.rb:328:in `block in run'
puma (4.3.5) lib/puma/thread_pool.rb:134:in `block in spawn_thread'

Attachment unique constraints fail while uploading duplicate file

Hi, I'm very interested in using this gem and probably send patches. So far I've found this:

class Site < ActiveRecord::Base
  has_many_attached :files
end

Attaching a file twice throws a constraint error:

site = Site.create
site.files.attach io: File.open('/tmp/somefile.jpg'), filename: 'somefile.jpg')
site.files.attach io: File.open('/tmp/somefile.jpg'), filename: 'somefile.jpg')
=> ActiveRecord::RecordNotUnique: SQLite3::ConstraintException: UNIQUE constraint failed: active_storage_attachments.record_type, active_storage_attachments.record_id, active_storage_attachments.name, active_storage_attachments.blob_id

Should IpfsService catch duplicate Attachments and remove them? Also getting the last Attachment without a query feels weird, wouldn't it be better to change it to something like Attachment.find_by(blob: new_blob)?

I'll prepare a PR after discussing, thanks!

Question about direct uploads

I was checking the direct uploads feature, from what I understand the file is going to be uploaded directly to the IPFS API, but this needs to be the uploaders local node or otherwise an IPFS node that's open to everyone, right?

Wouldn't it be better to generate an adhoc URL like DiskService, receive the file and internally upload it to the server's IPFS node that can be local or anywhere else, but not publicly open?

If you're interested I can write a patch, and I think this will remove the need for monkey patching ActiveStorage::DirectUploadsController and ActiveStorage::Blob, unless there's a need for this use case.

Ruby 3.0.0 + Rails 6.1.1

wow I was very curious to find this Rails gem, I would like to know if you would have problems using it in Ruby 3.0 with Rails 6.1.1, since I'm starting to use them as an experiment.

Anyway, I've just created a fork in case I have problems and see if I can use it. I really liked this gem

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.